-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Syncing for offline use not working #731
Comments
Just a couple notes about this issue:
Solving this issue requires knowledge of PouchDB and serviceworkers. If you have a question on the current code and/or those technologies, please feel free to ping me (@jkleinsc) |
I'd like to try fixing this if no one else does. Not sure how long it'll take since I'm new to both PouchDB and Service Workers. |
@tangollama I'd like to pick this one up |
@jkleinsc I closed all the tabs while server was running, then cleared all the localhost cookies. I already had some entries so I didn't use the test data. Left the app running for 5 mins. Turned off the server and the records are still showing. |
@mdarmani Perhaps you could also check this discussion out. I can confirm the problem mentioned. |
@mdarmani since @gnowoel asked first, I'd like to give @gnowoel this issue @gnowoel it is yours unless for some reason you have changed your mind about it. A couple of notes:
toolbox.router.get('/db/main/_all_docs', function(request, values, options) { This code is using https://github.com/GoogleChrome/sw-toolbox to add network proxies for calls to couchdb. These calls try to get the data from the network, but if that fails they grab the data from the local pouchdb pouchOptions.ajax.headers['x-local-pouch-request'] = true; and then in the |
@jkleinsc Thanks for your guidance! Will check it out. |
@jkleinsc No fix yet. Just some random findings :) In my experiments, I tried to directly wire the local Pouch to the remote Couch, but the problem still persists. Considering the requests triggered within a service worker will not go through the proxy routes, I guess the reason should not be self-syncing. From what I saw, the initial replication always worked, but it then just paused indefinitely. I tried many ways to rule out the unrelated facts, like writing a service worker by hand, upgrading PouchDB, and even disabling Ad blocker. But no matter what, the syncing still doesn’t work. Then I moved the syncing part to the web page (outside of the service worker), and suddenly everything just went fine. So I suspect it has to do with how we use PouchDB. We currently create the PouchDB database in two places, one in the web page for querying database, and the other in the service worker for syncing (and falling back, but never used I believe). Although we use the same name when creating and they are actually the same instance in the IndexdDB, but this arrangement might break syncing somehow. Not sure why though, because it should be legal to use one database in multiple tabs. Is it missing change events? Did it work before? If this is what happened, I think we have at least two choices:
I learned the first approach from worker-pouch, and the second one seems to be what are currently using. No idea which is better. But I think we need to remove the PouchDB from the web page either way. But is it really the root of the problem? What's your thoughts on this? |
@gnowoel thanks for the research. The local db created in the web page
The code in the service worker basically does the same thing as worker-pouch except it doesn't do any of the work in the web page thread. |
@gnowoel I just retested this and everything worked correctly for me offline. Can you retest and see if it works for you with the latest? |
@jkleinsc In my case, the initial syncing always works, but the subsequent changes from either end won't be populated to the other one. I'm experimenting with a minimal setup (only |
@jkleinsc I still see the same problem in my mini setup. It works for the initial replication, but no syncing happens on data change afterwards. Before testing, I first clear the data and unregister any existing Service Worker. Then I do a hard reload ( localMainDB.info().then(function(info) {
console.log(info);
}); This way, I can change a record and see if it's populated to the remote CouchDB. I can also do it in the other way around, by manually updating a record in CouchDB with Futon/Fauxton, and checking if it has been pushed back to the local PouchDB in the Service Worker's console window. I check the status of the Service Worker in this page: No idea about why syncing doesn't work in my testing. Does it have to do with the fact that a Service Worker is stoppable? It would be nice if you could take a look at the |
@gnowoel as far as I can tell I asked on the PouchDB slack about this issue and here is what Nolan Lawson (one of the PouchDB maintainers) had to say: jkleinsc [1:40 PM] nolanlawson [1:43 PM] [1:44] |
Not sure about this but perhaps check if the ember-pouch |
Nolan Lawson's suggestion is truly inspiring. Will see what I can do with the one-shot approach. |
@jkleinsc I managed to make the Background Sync approach basically work and here's how. In the web page:
And in the service worker:
This arrangement however has some known problems:
A sample app can be found here. This is just for your consideration and I have no idea if it's applicable to HospitalRun. I think I need your guidance on what to do next. |
@gnowoel thanks for your work on this. I have a couple comments:
|
@gnowoel I have been meaning to get back to you on this but I have been pretty buried lately. Here's an update based on learnings from Offline Camp.
|
@jkleinsc Thanks for the update and sorry for my late. I haven't got a chance to look into this issue until today. The Background Sync approach used to work in my test app, but somehow the sync events are never triggered in today's experiments. So, before I can figure out how to integrate Push API and other ideas you mentioned above, I'd like to try making Background Sync work first. No idea what happened. But will report back to you as soon as I've made any progress. |
@jkleinsc I couldn't get Background Sync working again. So I downloaded the official Background Sync demo and hoped to find out where I did wrong. But to my surprise, the app failed on all Chrome, Opera and Firefox on my localhost. And when it failed, Chrome didn't output any error message. However, the online version works fine for Chrome. My OS and browsers are up-to-date:
|
@gnowoel one thing I forgot to mention is that Background Sync is only currently supported in Chrome, so until other browsers implement it, it won't work there. As far as the demo not working, that is strange. Maybe it had to do with running on localhost? The one thing I observed was that I needed to toggle my internet connection in order to test the background sync vs just turning off the web server. The spec seems to indicate that it is tied to network connection, not server reachability:
In theory you could polyfill background sync in other browsers by listening for the online event (see https://developer.mozilla.org/en-US/docs/Online_and_offline_events) and then sending a message to the service worker to fire the sync event. |
@jkleinsc Toggling network connection did the trick (Guess it's becuase of my VPN or something). Now the (To run the Background Sync demo app locally, I also need to adjust the scope when registering the service worker.) If you don't mind, here I have some stupid questions to ask. Push API As far as I know, Push API would basically do the same thing as Primary database It looks like we’re using remote CouchDB as the primary database. Is there any specific reason that we can't use local PouchDB directly and let it worry about how to sync behind the scene? That way, we don't have to deal with database switching and the timing gap caused by it. (Say we add a record online, and go offline immediately. The newly added record would disappear because it has not been synced back to the local database yet.) Thoughts I'm thinking if we could do the following?
Since we don't connect to the remote CouchDB directly, there's no need to intercept the query requests in the Service Worker. Now the responsibility of the Service Worker would be:
|
@gnowoel I think maybe a little background might help explain things further. As I investigated this problem further, I found out that IndexedDB (which PouchDB uses behind the scenes) blocks the DOM: https://nolanlawson.com/2015/09/29/indexeddb-websql-localstorage-what-blocks-the-dom/ Given this, I decided two things:
Long term what I would like to see is a way of users selecting what mode they want to run in. For example:
Does that make sense? As far as the PUSH API is concerned, the difference is who is listening to the changes feed and which db is the "primary database". You could in the browser listen for changes on the remote DB, but that would require a constant polling to pull in changes vs the server initiating a push when a change actually happens. |
@jkleinsc Yes, it makes sense. Thanks for the detailed explanation! Will see what I can do... |
@jkleinsc I updated the code with PR #820. It's by no means a complete solution, but I was thinking if we could:
What I did is just making Background Sync work, and in my simple tests, the problem seems to be fixed. My implementation looks somewhat naive, because I use global variables for sharing database instances. There must be a better way, but I just don't know. The initial sync happens in the main thread, because I can't do it in the service worker. Tried to put the code in different places, inside or outside of a function, in the To check it out, perhaps you could add or change some records offline, and then go online and refresh the page. After a while, the databases should be synced. Hope this is good enough at least for now. |
Expected behavior:
When a user is online records should be synced to the user's browser for offline use.
Actual behavior:
Records are not synced for offline use.
Steps to reproduce:
Type in localhost (or whatever host your app is running on) and you should see an entry like the one in the screenshot. Click on the entry and then click on the
X
on the right hand side of the screen.ember serve
or via hospitalrun-server.https://github.com/HospitalRun/hospitalrun-frontend/blob/master/sample-data.txt
Screenshots (if applicable):
N/A
OS and Browser:
Chrome 53.0.2785.143 (64-bit)
The text was updated successfully, but these errors were encountered: