cloudant / CDTDatastore

Cloudant Sync iOS datastore library.
Apache License 2.0
175 stars 53 forks source link

CDTReplicationcomplete is received before replication is actually complete. #400

Closed AjayHegdeK closed 6 years ago

AjayHegdeK commented 7 years ago

CDTDatastore: 1.2.2

iOS - 9 and above There are 2 applications both are accessing CDTDatastore in a single device. When I switch between apps I am getting database download complete even before it is actually completed. And same issue also occurs when you switch on and off internet frequently.

Detailed log:

CDTDatastore: 1.2.2

iOS - 9 and above There are 2 applications both are accessing CDTDatastore in a single device. When I switch between apps I am getting database download complete even before it is actually completed. And same issue also clientIDcurs when you switch on and off internet frequently.

Detailed log:

2017-10-27 18:05:57:782 clientID Production[733:188615]

emlaver commented 6 years ago

We’ve been unable to reproduce this, but are continuing to investigate. We recommend that you configure replication policies for your applications.

AjayHegdeK commented 6 years ago

Hi, I have gone through replication policies and followed the document as is, but still issue exists. Our sync time is around 3 mins we have more 10k documents, can you please try out with minimum 10k documents. Step1: start downloading we have used sync mechanism in the following way

Step2: Connect and disconnect frequently, switch on and off wifi

OR

Switch between two apps downloading data from cloudant

Step3: It will reach completion before downloading all files

func replicatorDidComplete(_ replicator: CDTReplicator) {

}

this method gets called.

Please let me know: if you try syncing using more data for 3 minutes at least to download than you will be able to reproduce.

tomblench commented 6 years ago

@AjayHegdeK I can't see all of your code from your sample, so I can't see how closely you followed the sample in the replication policies guide. If you follow the sample, syncInBackgroundWithCompletionHandler will ensure that these tasks are started as background tasks using a unique task group, and call startReplications periodically to do the actual replication.

(I would expect you to use the startWithTaskGroup:error: flavour of the start method on the replicator, so you can control the execution of the sync as a background task, which means that it won't exit when the user changes apps or your app gets interrupted in some other way).

I tried some sample code based on the replication policies guide, and it works, but one thing to note is that the completion handler is called on failure or success. You need to check the status of the replicator to see if it failed. So when I ran the code and switched off Wi-Fi, the completion handler was called even though the sync process failed.

tomblench commented 6 years ago

@AjayHegdeK note also that in our policies guide syncInBackgroundWithCompletionHandler only waits 30 seconds and then calls the callback, so a long replication my not be finished by this point. You will need to adjust your time out accordingly.

tomblench commented 6 years ago

@AjayHegdeK I had another look at your logs and I saw the App going into background message. That message is triggered by this code.

You can see that the replicator receives the appBackgrounding notification and stops the replication. We don't think this is the right behaviour for your requirements, and we are thinking of removing this method. However, this is a behaviour change for other users so we have to consider the impact carefully. I think we should be safe to remove it, since users who want the old behaviour can receive this event themselves and stop the replication.

AjayHegdeK commented 6 years ago

Hi @tomblench thank you for researching the issue. Will look forward to the solution. I hope the log I have sent is sufficient to look into the issue, If you need more information please let me know.

navaneet commented 6 years ago

Apart from the background issue already mentioned one of the primary concerns that we are having is that replicatorDidComplete is called with status CDTReplicatorState.complete when the network is switched on and off very frequently. So after receiving error status couple of times suddenly CDTReplicatorState.complete status is provided in replicatorDidComplete delegate even though the replication has been done partially only. This scenario happens even when the app is in foreground and even if we use task group.

Since we have no way of knowing how many documents need to be replicated prior to replication starting hence without proper delegate callbacks it's impossible to deduce if replication has successfully finished or only partially. This was tested recently on iOS 11 and the same issue could be reproduced.

    func replicatorDidComplete(_ replicator: CDTReplicator) {
            // Brings indexes up to date with the contents of the datastore.
            datastore?.updateAllIndexes()
            //check whether replicator state is really complete
            if replicator.state == CDTReplicatorState.complete {
                completionHandler?(.completed)
            } else {
                completionHandler?(.errored)
            }
        }