Skip to content

PFEventuallyQueue sync #1181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ayoze opened this issue Sep 5, 2017 · 24 comments · Fixed by #1182
Closed

PFEventuallyQueue sync #1181

ayoze opened this issue Sep 5, 2017 · 24 comments · Fixed by #1182

Comments

@ayoze
Copy link

ayoze commented Sep 5, 2017

Hello,

I am using Parse in some of my offline-online projects (apps which needs offline information storing and syncing when possible with the server. Local datastore works good here for me).

The only strange behavior is that the PFEventuallyQueue has no idea about the state of the network connection IMO. The scenario is:

  1. Device with no internet connection
  2. Create the object locally, pin it to the local datastore and call saveEventually
  3. With the app opened, connect to a wifi network
  4. Nothing happens. Data is not synced in the server
  5. Close app and reopen it. Data is now synced in the server

Would be great to have the chance to force the sync to of this queue if the app can detect a working internet connection with Reachability or something.

Many thanks in advance.

@brianyyz
Copy link

brianyyz commented Sep 5, 2017

I use the Reachability framework so that the app can respond to the loss of network and return of network.
https://github.com/ashleymills/Reachability.swift

If the reachability listener reports a network status change it can push a notification that other parts of the app can listen for and respond to.

In your case when your reachability instance reports return of network connectivity you could force the necessary sync.

@flovilmart
Copy link
Contributor

@ayoze the PFEventuallyQueue is actually listening for reachability changes, if you look at the code you’ll see by yourself. What you describe is probably a bug. I’ll check it out.

What version of the SDK are you running?

@ayoze
Copy link
Author

ayoze commented Sep 5, 2017

Yes @flovilmart, I've seen that in the code, but not sure why it is not working. The SDK I am using, from cocoapods is: Parse (1.15.1)

@flovilmart
Copy link
Contributor

can you try the 1.15.2?

@ayoze
Copy link
Author

ayoze commented Sep 5, 2017

@flovilmart same behavior. The app is now like in a "hold" state.
I can see the new object created for a fraction of a second when I query the local datastore. Then, when the second callback comes (from server) it disappear.
In the server the object has not been created (checked in the dashboard).

If I disconnect from wifi, I can see the new object. If I connect, it disappear immediately. When I close (kill) the app and reopen, it syncs and everything works as expected.

@ayoze
Copy link
Author

ayoze commented Sep 5, 2017

@flovilmart just trying to put some light here... in PFReachability.m:

  • Method _reachabilityCallback is called correctly when network state changes (line 32).
  • Method setFlags is called correctly
  • Method _notifyAllListeners is called correctly
  • Inside _notifyAllListeners, array _listenersArray is empty
  • Obviously the reachability:didChangeReachabilityState: method in PFEventuallyQueue is not called.

any ideas? I think the

@flovilmart
Copy link
Contributor

So you’re using the local data store, with saveEventually right?

@flovilmart
Copy link
Contributor

I'm looking into it.

@flovilmart
Copy link
Contributor

@brianyyz it's already internally wired up for that.

@flovilmart
Copy link
Contributor

@ayoze can you try the branch that I just pushed, this should be all good now :)

@brianyyz
Copy link

brianyyz commented Sep 5, 2017

Thanks @flovilmart - I'm updating apps so I'll look at moving over to PFEventuallyQueue !

@ayoze
Copy link
Author

ayoze commented Sep 6, 2017

many thanks @flovilmart ! It seems to be fixed but if you don't mind, let me make some more testing, ok? I will open another issue with a different local datastore related problem :/

@ayoze
Copy link
Author

ayoze commented Sep 6, 2017

@flovilmart it seems the PFEventuallyQueue is terminated for any reason at start. I think the problem is in the method ParseManager::eventuallyQueue... the CommandCache queue is terminated at the application start so no other commands can be enqueued (I have not researched if the command queue is created again if needed, sorry).
When I try a deleteEventually in the future, the field "isDeletingEventually" is not marked as 1 in the sqlite database.
Strangely, the field isDeletingEventually inside the json in the database is marked as 1!

captura de pantalla 2017-09-06 a las 13 59 16

@flovilmart
Copy link
Contributor

We terminate a queue that is useless and it prevents a retain cycle, as far as I know, the queue that gets terminated is not references outside the scope of eventuallyQueue, so there’s no way it can be useful. The only queue you should have in memory is the PinningEventuallyQueue AKAIK.

@flovilmart
Copy link
Contributor

I’ll still look into the lifecycle of the PFCommandCache.

@ayoze
Copy link
Author

ayoze commented Sep 6, 2017

Another strange thing happening in the same object I talked before (HorarioFranja).
To let the user delete it, I have a method with this code in a category of PFObject:

-(BFTask*)unpinAndDelete
{
    return [[self unpinInBackgroundWithName:[NSString stringWithFormat:@"xx%@xx", self.parseClassName]] continueWithSuccessBlock:^id _Nullable(BFTask<NSNumber *> * _Nonnull t) {
        
        if ([PFReachability sharedParseReachability].currentState != PFReachabilityStateNotReachable)
        {
            return [self deleteInBackground];
        }
        
            [self deleteEventually];
        
        return nil;

    }];  
}

This method unpins the object from LDS and then do a delete (eventually if no internet access is recognized, delete directly otherwise).
Pin name is: xxHorarioFranjaxx (same for pin method).

The point is that when I call this method (without internet connection), the object is removed from the database, but instanly after that is reinserted. I don't know how this happens but I can see the list without the object, and when I reload it, the object is again there.
I have set a breakpoint in the reloadTable call and checked the database in this moment and, exactly: 5 elements before reload, 6 elements when I manually reload the table again. I have set some other breakpoints in the PFOfflineStore.m code and I see some insertions when I am unpinning/deleting. Crazy :S

@ayoze
Copy link
Author

ayoze commented Sep 6, 2017

My pin-and-save method, if needed:

-(BFTask*)pinAndSave
{
    
    
    return [[self pinInBackgroundWithName:[NSString stringWithFormat:@"xx%@xx", self.parseClassName]] continueWithSuccessBlock:^id _Nullable(BFTask<NSNumber *> * _Nonnull t) {
        
    
        if ([PFReachability sharedParseReachability].currentState != PFReachabilityStateNotReachable)
        {
            return [self saveInBackground];
        }
        
        [self saveEventually];
        
        return nil;
    }];
}

@flovilmart
Copy link
Contributor

In your unpinAndDelete, is it the delete eventually that add to the store as deleted?

@ayoze
Copy link
Author

ayoze commented Sep 6, 2017 via email

@flovilmart
Copy link
Contributor

I believe deleteEventually is re-pinning your object for some reason, can you try remove it?

@ayoze
Copy link
Author

ayoze commented Sep 6, 2017

Hmmm even stranger: when I remove the deleteEventually, the object is not removed at all in the first load nor in the second. Like if the unpin is not working...

@flovilmart
Copy link
Contributor

Would you be able to write a test and open a PR with this failing test?

@ayoze
Copy link
Author

ayoze commented Sep 6, 2017

Well, I'm not much into unit testing :( If I can provide more information...
By the way, I've seen that the disappear-appear problem only happens when the object is first created, after that, if I call again the unpinAndDelete it does not disappear at all. I can post the raw objects in the database before and after calling the unpinAndDelete method.

Does anybody know any way I can bypass this bug? I just want to pin+sync and unpin+sync objects!

@flovilmart
Copy link
Contributor

Well, I'm not much into unit testing

it's never too late to get started, the project has a high coverage of many use cases, and that would really help debunk the issue as I have trouble understanding your whole flow.

writing a test would really help isolate the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants