Skip to content
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

Full resync? #42

Closed
martindiphoorn opened this issue Dec 1, 2014 · 7 comments
Closed

Full resync? #42

martindiphoorn opened this issue Dec 1, 2014 · 7 comments

Comments

@martindiphoorn
Copy link
Contributor

The documentation speaks about: db.syncable.delete(url).
However it seems to me it does not exist in the code.

I want to use this to be able todo an full resync from scratch.
What is the best aproach to do that?

@dfahlander
Copy link
Collaborator

As the delete() method is not implemented yet, you could work around it by deleting the database and recreate it. The delete() method will be implemented by removing the sync-node representing the particual remote endpoint. If you feel lucky, you could give it a try to implement it. Might need to try review the code to find whether we would need to await or cancel existing sync operations before deleting the node. The Observable and Syncable addons are in alpha and may need some refactoring.

@martindiphoorn
Copy link
Contributor Author

I'm aware that is alpha, but it can only get out of alpha by using it. So im using and trying to help you out if i can. But i need to learn the way you program :D

I have already been trying to implent it.
My idea was to disconnect the url (which was done outside this code). Call the Delete and wait for the promise (Didn't get the promise to work so left it out). Connect the url again.

This was the code i had:

db.syncable.delete = function (url, options) {
            db._syncNodes.where("url").equals(url).modify(function (node) {
                db._changes.where('node').equals(node.id).delete();
                db._uncommittedChanges.where('node').equals(node.id).delete();

                node.appliedRemoteRevision = 0;
                node.remoteBaseRevisions = {remote:0, local:0};
                db._syncNodes.put(node);
            });
        };

However it didn't worked fine. One problem was that the synchronisation keeps giving an wrong revision number.

Maybe you can help me out here? Thanks in advance.

@dfahlander
Copy link
Collaborator

I would love to have a look into it when I get a chance. Please remind me if I don't! Spontanously, without having looked into the source of the addon for a while, I could see one possible issue with your code snippet; promises aren't returned or waited for + I believe the node should not be recreated in the delete() method. Also, would be nice to encapsulate the method in a transaction to ensure atomicy as well as not missing out any failed operation. Without having tested it, I would suggest something like the following:

db.syncable.delete = function (url) {
    // Surround with a readwrite-transaction
    return db.transaction('rw', db._syncNodes, db._changes, db._uncommittedChanges, function () {
        // Find the node
        db._syncNodes.where("url").equals(url).first(function (node) {
            // If not found, resolve here (nothing deleted), else continue the promise chain and
            // delete the node and all that refers to it...
            if (!node) return; else return db._syncNodes.delete(node.id).then(function(){
                return db._changes.where('node').equals(node.id).delete();
            }).then(function(){
                return db._uncommittedChanges.where('node').equals(node.id).delete();
            });
        });
    });
};

If the use case is force a full resync, the caller could do:

db.syncable.disconnect(url).then(function(){
    return db.syncable.delete(url);
}).then(function(){
    return db.syncable.connect(protocol, url, options);
});

@martindiphoorn
Copy link
Contributor Author

Ah thats a great starting point... Actually it worked almost out of the box 👍

This is the current version i have working:

        db.syncable.delete = function (url) {
            // Surround with a readwrite-transaction
            return db.transaction('rw', db._syncNodes, db._changes, db._uncommittedChanges, function () {
                // Find the node
                db._syncNodes.where("url").equals(url).first(function (node) {
                    // If not found, resolve here (nothing deleted), else continue the promise chain and
                    // delete the node and all that refers to it...
                    if (!node) {
                        return;
                    } else {
                        var nodeId = node.id;
                        return db._syncNodes.delete(nodeId).then(function () {
                            return db._changes.clear().then(function () {
                                return db._uncommittedChanges.where('node').equals(nodeId).delete();
                            });
                        });
                    }
                });
            });
        };

There is one small problem. The _changes tableStore does not have an node so i could not search on it. Trying to change it to source dit not work either. I also see that i have lots off sources with "null" values in de _changes.
However if I do an resync i don't care about the changes for now. So i used a clear for that part.

After that the sync is working in my project!

If you like the change, i'm willing to send a pull request if you like that.

Thanks

@martindiphoorn
Copy link
Contributor Author

Send a pull request.

@dfahlander
Copy link
Collaborator

Thanks! I've merged the pull request in. Had to change one thing: Instead of clearing _changes, I only delete changes that were only still queued because of the deleted node. If there were other nodes alive, they may need those changes.

        db.syncable.delete = function (url) {
            // Notice: Caller should call db.syncable.disconnect(url) and wait for it to finish before calling db.syncable.delete(url)
            // Surround with a readwrite-transaction
            return db.transaction('rw', db._syncNodes, db._changes, db._uncommittedChanges, function() {
                // Find the node
                db._syncNodes.where("url").equals(url).first(function(node) {
                    // If not found, resolve here (nothing deleted), else continue the promise chain and
                    // delete the node and all that refers to it...
                    if (!node) {
                        return;
                    } else {
                        var nodeId = node.id;
                        // Delete the node
                        return db._syncNodes.delete(nodeId).then(function() {
                            // When this node is gone, let's clear the _changes table by
                            // from all revisions older than the oldest node.
                            // First check which is the currenly oldest node, now when we have deleted
                            // the given node:
                            return db._syncNodes.orderBy("myRevision").first();
                        }).then(function(oldestNode) {
                            // Delete all changes older than revision of oldest node:
                            return db._changes.where("rev").below(oldestNode.myRevision).delete();
                        }).then(function() {
                            // Also don't forget to delete all uncommittedChanges for the deleted node:
                            return db._uncommittedChanges.where('node').equals(nodeId).delete();
                        });
                    }
                });
            });
        };

@martindiphoorn
Copy link
Contributor Author

Looking great, going to test this.

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

No branches or pull requests

2 participants