-
Notifications
You must be signed in to change notification settings - Fork 41
Offline synchronization #71
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
Comments
If not, is this something which you think could be easily done by looking at the existing browser version? Would you accept PRs on that issue? |
Hey! We don't have plans for adding offline sync to the Android SDK in the near future, but we will gladly accept PRs implementing this feature! Beware, the implementation won't be exactly easy. If you decide to use the same design as we have in the javascript/browser version, then you need to:
Having said that, I think the isomorphic "replicate from anywhere to anywhere" design of the JavaScript version is a bit overkill for Android apps. A simpler design focused on offline sync may work better:
|
Did you ever consider using the Robospice component for doing this ? It would also enable caching pretty well the data repo. I'm not dev crack enough for doing this, but definitively may help in doing this. |
@bajtos In the suggestion you make:
Are you suggesting that the Android app could still make use of Loopback's Syncronisation API (such that the Android client "looks like" a client Loopback instance, but actually isn't), or rather are you suggesting it would be better to simply roll your own sync strategy? I've stumbled across this issue, and the documentation about the Loopback Offline Syncronisation feature, because I want to synchronise objects between my Android application and Loopback backend. I am using the classic combination of SQLiteOpenHelper, ContentProvider, and SyncAdapter to handle local storage and server synchronisation. For my purposes I only need simplistic synchronisation. For the client to check for data changes at the backend in a way that minimises network use, what I was planning to do is to set the However, I was just curious about whether I could simply enable Sync on the models in my Loopback server to automatically provide me with extra endpoints to provide diffs, revisions, etc. |
IIRC, my idea was to leverage the server-side Synchronisation API that's already available and implement a custom Android client invoking this API. I am not familiar with Android's ContentProvider/SyncAdapter feature, after a quick read of https://developer.android.com/training/sync-adapters/index.html I think they may be the right abstractions to use. The synchronisation (we call it "change replication") implemented by LoopBack does not rely on timestamps (like If you are looking for one-way synchronisation only (Android client fetching updates from the server), then I think it may be reasonably easy to implement a SyncAdapter using the current change-replication API.
Yes, the flag is called Our docs contains also a list of methods that are related to change replication (link), see also the source code of the method implementing change replication: lib/persisted-model.js#L1120-L1308. I think the simplified algorithm for pulling the changes from the server would be along these lines:
|
@bajtos Thank you very much for the detailed guidance. As you suggested I have enabled One concern I have is that, for a client to see if there are new changes at the server using the algorithm you propose, the client would be bumping up the checkpoint number ever time it polls for changes. Does this risk creating any unnecessary bloat in the database over time? The slight variation to this strategy could be for the client to simply do The other concern I have is how much the change history in the database will grow over time, which might be an unnecessary overhead if I don't need the change history (when all I really want to achieve is "is the server data newer than my local data?". Is it possible to remove older change history? Finally there's this 'known issue' in the documentation:
Does this mean that if the myModels collection contains objects created by different users, and a particular client only wants diffs to models owned by that particular user, would I have an issue using the Sync API? |
Ah! Using Robomongo I now see that the checkpoint just exists as one record. And, if I ever wanted to, it seems I can safely trim the contents of myModels-Change. I still need to get my head around the meaning of the user access issue. Perhaps it doesn't concern me if I don't use the replication feature of the API. |
I guess if you have many clients that are checking for changes often, then the checkpoint number can eventually overflow int32/int64 limit. The variation you proposed looks sensible to me, as long as the cost of the extra request is not significant.
Yes. Right now, the built-in sync API does not provide any way for filtering the model instances. I.e. your change list will include instances created by other users, and the "bulkUpdate" endpoint will allow the clients to update any instances, including those created by other users. BTW this is true for the built-in I think there may be a solution though:
// common/models/my-model.js
module.exports = function(MyModel) {
// the code here is not tested, may not work out-of-the-box
MyModel.disableRemoteMethod('changes');
MyModel.disableRemoteMethod('createUpdates');
MyModel.disableRemoteMethod('bulkUpdate');
// etc.
MyModel.myChanges = function(since, options, cb) {
var currentUserId = options && options.accessToken && options.accessToken.userId;
if (!currentUserId) {
var err = new Error('Not Authorized');
err.statusCode = 401;
return cb(err);
}
// assuming "owner" is the FK mapping to users
var filter = {where: { owner: currentUserId }};
this.changes(since, filter, cb);
};
MyModel.remoteMethod('myChanges', {
accepts: [
{arg: 'since', type: 'number', description:
'Only return changes since this checkpoint'},
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
],
returns: {arg: 'changes', type: 'array', root: true},
http: {verb: 'get', path: '/my-changes'},
});
}; (The code is relying on strongloop/loopback#1495 which was not published to npmjs.org yet.) Loosely related:
@TrevorPage if you manage to implement an Android client using my suggestions and release it in a form that other LoopBack users can use, then we would be happy to feature it on our http://loopback.io/doc/en/community/index.html page. |
@bajtos Thank you again for taking the time to provide the further advice. Your proposed Another idea is to expand my I will definitely try to split a stand-alone Android demonstration of this from my project if I can. A few questions/concerns that still exist are:
|
I think this is definitely a feature that we would like to eventually implement, but unfortunately it's not on our near-term roadmap. cc @raymondfeng @ritch ☝️
Agreed - having a client to generate globally-unique ids (like ObjectIDs) and the server letting MongoDB to generate these ids should be equivalent to using LoopBack's GUID generator.
The strict validation is required to reliably apply changes through LoopBack API. Consider the following use case:
Also:
I think you should be able to code your application in such way that will avoid these two problems. @crandmck There is quite a lot of useful information in this thread, I think we should capture it in our documentation. Are my comments clear enough so that you can write the first draft yourself, or should I write it myself? |
@bajtos Let me try to throw something together and then I'll hand it off to you. It's mostly just the last few comments in this issue. I made a few edits, but didn't have time to really make it coherent. Perhaps you could take a swing at it? Once we get it in better shape, I will move it into the actual docs, but for now the wiki page is an easy place to collaborate. |
@bajtos I haven't had much time to work on this. Could you make a pass through https://github.com/strongloop/loopback.io/wiki/Offline-sync-for-Android-SDK-%5Bworking-draft%5D and remove anything irrelevant, and add anything missing. Then, I'll make another pass and we can open a PR from there. |
Added to the backlog, it may take a while before I'll have time to work on this. Is the wiki open for editing by people outside of our org? Can e.g. @TrevorPage review and edit that wiki page? |
@bajtos No wiki's are open to public ATM on any project (I found some garbage in the past and cleaned it up before). However, I do suggest in your case to open it up temporarily and lock it down again after. |
Actually the loopback.io wiki should be editable by any GH acct, because I have not checked the |
I'd love to contribute to this any way I can. I'll see what I can do. :) |
@TrevorPage The wiki is now open, feel free to edit this repo's wiki or the loopback.io wiki, we can sort out the organization later. |
For this issue, I'd start with https://github.com/strongloop/loopback.io/wiki/Offline-sync-for-Android-SDK-%5Bworking-draft%5D which has most of the pertinent content. It just needs cleanup and editing. |
Hey!
Are there any plans to add offline synchronization capabilities as described here [1] to the Android/iOS SDKs? I found some google groups threads from 2014 on that topic, but no changes since then. Is this feature already scheduled?
Thank you!
[1] http://docs.strongloop.com/display/public/LB/Synchronization
The text was updated successfully, but these errors were encountered: