saveEventually in Parse SDK sometimes saving only on app reload - parse-server

I am using saveEventually in Parse iOS SDK instead of SaveInBackground, just in case there is no network available. Most of the time the save happens immediately. However, sometimes (presumably if there's a bad network connection) I'm having multiple items just getting stuck and nothing is being saved even though some time has passed and a network has clearly been available. The only way to push up all stored items and save them is by closing the app completely and then reopening it, and usually this will immediately save all!
I have found this mentioned from Parse:
"Objects saved with saveEventually will be stored locally in an on-disk
cache until they can be saved. They will be sent
immediately if possible. Otherwise, they will be sent the next time a
network connection is available."
That is clearly not the case in my experience.
I am wondering why the SDK is not realizing the network is available and if I can do anything to force it to try more often. I am also wondering how many times SaveInBackground would try to find a network and save, as I believe it will try a few times at least and if so I could possibly switch to trying that method.
Any ideas?

Related

MS Access occassional "Cannot open any more databases" error

I have an MS Access (2013) application with a split database. Everything seems to run smoothly except for occasionally I will get Error 3048: Cannot open any more databases.
The error occurs when the front end tries to run vba code which involves pulling data from the back end and will stall on any line with: Set DB = OpenDatabase() or DoCmd.RunSQL() commands.
The strange thing is that this error seems to be time based. I can access the back end hundreds of times without error if I do it quickly enough but after some time has passed (~1 hr) the error shows up. In fact, I can open the application and leave it running in the background (with no code running) then go back into it after an hour and I will get the error the first time the code tries to open the back end.
I've searched the length and breath of this site and google for solutions so I know this error has been addressed before. To save people reiterating the usual fixes I will list what I've tested for so far with no success:
Recordset limit: I'm not leaving any recordsets open, every time I open one I make sure to close it. The same for the databases. All my requests
to the back end are done via 3 or 4 vba functions and each of these has
a Rec.Close or DB.Close corresponding to every OpenRecordset()
and OpenDatabase() and I never have more than 2 recordsets open at
a time.
Control limit: I have 151 controls on the biggest form in the application so I should be below the limit (I believe this is 245 for a single form?)
Corrupt database: I've copied all my forms and code to a new Access database and run a Compact and Repair.
Machine Issue: I've tested the application on several machines and reproduced the same error.
Anyway with most of the above situations I would expect the application not to run at all, instead of running fine for a set amount of time and then crashing.
Some other points of note:
Citrix Users: The users are split between normal windows machines users who are experiencing this error and others who are using the application through a virtual desktop software (Citrix) who are having no issues. Unfortunately I don't know enough about this virtual desktop to really work out what that implies.
Background vs Foreground: Some users have claimed that the application only crashes if it has been running for a long time AND they switch over to another program and switch back. I've confirmed that simply switching between the application and other programs doesn't cause it to crash but haven't yet been able to leave it running in the foreground long enough to confirm if it crashes without switching between programs.
I've been struggling with this for days, anyone able to help me out?

Archiving object to a read-only file

I have my app saving some objects into .sav files using NSKeyedArchiver archiveRootObject: toFile:; however, I realized that if a user were to open up one of the .sav files in textedit and change it at all, the app would fail to unarchive the objects next time it opens, and would stop working.
Is there any way I can archive the root objects to read-only file or otherwise stop users from editing them? They're buried in application support, so not super accessible, but I'd like to play it safe.
Your application should be able to handle that kind of error.
Also, suppose you did archive the data and then set the file to be read-only. What would stop a determined user from making it read-write again?
You could use some kind of checksum to verify file integrity, though, but you would probably have to roll your own in that case.
I don't think there is a way for you to avoid potentially losing the saved state (in the end the user could simply delete the file), however if you are worried about the user manipulating the data, you should look at NSSecureCoding.
I believe that is a way to avoid unarchiving "corrupt" data and guaranteeing the integrity, I have not explored the topic further so I can't say for sure whether that would allow a scenario in which the contents of specific fields are changed (i.e object type is the same, but value is different).
In conclusion, I think it is better/safer to build your system with the idea of someone trying to circumvent your security in mind and instead of trying to stop the user from manipulating/deleting the data, just making sure invalid data is not loaded in. For example in case of invalid/corrupt/missing data just reverting back to the default values (i.e as if the app is launching for the first time).

How to know that coredata does not load fault?

I grab data from the web and then I save that in coredata. Not all data must be created new. If the data is the same with previously stored data, then we use old data.
To speed up the saving process, I prefetched old data.
Turns out it's still slow. The saving process is still slow.
I suspected that core data makes IO trips again after the prefetch.
How do we know whether it does again? Can we break on "IO" trip or something?
To monitor Core Data/SQLite activity, you can
Goto "Edit Scheme ..." and add "-com.apple.CoreData.SQLDebug 1" to the "Arguments Passed on Launch". Then you will get console output for all SQLite actions.
Profile your app with Instruments and the "Core Data" tool.

How to force a version conflict in iCloud

I have a working implementation of iCloud. Now I want to improve conflict handling by adding some merge functionality. I've been trying to come up with a consistent way of forcing a conflict for testing purposes but I haven't had luck so far, conflicts don't occur consistently when I expect them to occur. This might indicate that I'm doing something wrong, or maybe that I just misunderstood something about how iCloud works (yet another thing, I mean).
I'm using UIDocument and yes, I'm listening to the UIDocumentStateChangedNotification. In fact, I do get some occasional conflict notifications. Also, I only have one file in iCloud.
Having two devices using the same iCloud accout, here is the flow of events I was expecting to always cause a conflict:
Open the file on both devices (both devices are now correctly seeing the same content). Note: Here is the only time openWithCompletionHandler is called, after this it's never called again.
Make some change on device A and call saveToURL.
Wait some time to allow the change to propagate.
Make some other change on device B and call saveToURL.
Wait some time to allow the change to propagate.
EXPECTED: The app should be getting a conflict notification from iCloud. OBSERVED: A conflict does occur very occasionally, but most of the time what happens is simply that the UIDocument gets its UIDocumentStateEditingDisabled flag set and then cleared back after half a second or so (I'd guess editing is being disabled while the iCloud daemon is pulling the version from the other device and saving it in the local ubiquitous directory).
Much like a version control system like SVN, I was expecting the version from device B to cause a conflict because an "update" was required in order to get the version uploaded by device A.
Am I wrong expecting a conflict in the scenario I just described? Why? Is there any other way to consistently force a conflict?
Thanks!
I would have thought a better way to cause a conflict would be to:
Make sure both devices have an up-to-date copy of the data
Put both devices into Airplane Mode to prevent any iCloud updates
Change the data in the same place on both devices, each with different new data
Turn the network back on
Wait for the changes to propagate
From the docs:
Conflicts occur when two instances of an app change a file locally and both changes are then transferred to iCloud. For example, this can happen when the changes are made while the device is in Airplane mode and cannot transmit changes to iCloud right away. When it does happen, iCloud stores both versions of the file and notifies the apps’ file presenters that a conflict has occurred and needs to be resolved.
The way you are doing it (allowing time for sync, altering the documents differently) seems like it shouldn't cause a conflict.
iCloud works basically the same as version control system - except that you can only access the conflict versions (when conflict happens).
When a device pulled ver_1 from iCloud, edit, save, and find the server has a different version (ver_2 or newer) than it expected, a conflicted version will be created.
After the initial sync, you can:
turn off wifi on device B, edit & save.
edit on device A, save.
turn on wifi on device B.
A conflict will come soon.

File system operations (e.g. copy, delete, move) performed through ActiveSync - are they atomic?

I am developing an application in .NET Compact Framework 3.5, for Windows CE 6. I need to automate some data synchronization between the mobile application and a PC. So what I do is that, in the .NETCF application, I have a while loop that checks every few seconds, using System.IO.File.Exists(fullFilePath), whether the file I am expecting has been copied from the PC to the mobile device, through an ActiveSync connection.
Once the mobile app finds the file, it will open and read it using a StreamReader.
My problem is that, some times, File.Exists(fullFilePath) would return true, yet the subsequent use of StreamReader may fail with a FileNotFoundException.
Ruling out the possibility of the file getting deleted between the call to File.Exists() and the instantiation of the StreamReader, would anybody know how the exception may occur? Is it because file copy through ActiveSync is not atomic, such that the file is not actually ready for reading even though File.Exists() returns true?
A file copy is most certainly not going to be atomic. When you start the copy, the file is created, but has no data in it. As the file data gets written, the file "exists", but is not yet fully complete. You'd want to know not only that it exists, but that it's not currently in use (meaning the writer is done). Trying to open it exclusively would verify that.