nolanlawson / cordova-plugin-sqlite-2

Native SQLite database API for Cordova/PhoneGap/Ionic, modeled after WebSQL (UNMAINTAINED)
https://nolanlawson.com/2016/04/10/introducing-the-cordova-sqlite-plugin-2/
Apache License 2.0
168 stars 28 forks source link

Synching with PouchDB with attachments silently fails on Android #38

Closed ahodgkinson closed 6 years ago

ahodgkinson commented 8 years ago

Overview

  1. Our Android/Ionic/Angular app fails while syncing data with attachments from a CouchDB server to the local device's PouchDB
  2. We are calling PouchDB replicate.from(..) a CouchDB on a server, to an empty local PouchDB
  3. There are approximately 220 records, with 90 attachment files, a total of 60 MB, in the CouchDB
  4. There are two main symptoms:
    1. Neither the replicate.from() success nor error callback are ever triggered
    2. The app exits with message: "Unfortunately, Issue83 has stopped"

      Environment

Ionic/Cordova/Angular hybrid app, using PouchDB & cordova-plugin-sqlite-2, for Android for phones and tablets

issue-38.zip

Test App Source Code:

  1. Key files:
    • www/services/pouchdb.service.js
    • www/components/home/home.controller.js
nolanlawson commented 8 years ago

Thanks for the reproducible test case! I will take a look at this when I get a chance.

In the meantime I can tell you this: I do not recommend SQLite Plugin 2 for Android for 99% of use cases, and I especially don't recommend it for large binary attachments. In WebSQL and in Cordova plugins, binary data needs to be serialized when sent back and forth between the JavaScript context and the native code, which is enormously inefficient and may lead to crashes if you try to do it all at once.

Whereas in IndexedDB on Android, there is native support for Blobs, and so those Blobs can be directly saved to IndexedDB without ever reading anything into memory in JavaScript. (Try this with a <input type="file">, notice that if you save that Blob/File to PouchDB, then your memory usage inside the JavaScript environment will never increase, even if the file is huge.)

Another issue: since your documents are huge, you may want to use a smaller batch_size when replicating. PouchDB will try to insert all records in a batch into IndexedDB/WebSQL/SQLite at once, which can exceed your memory limitations if you're not careful. Another option is to break up your attachments into smaller attachments and spread them across documents.

Given we plan to manage and sync over 1 GB of PouchDB data with attachments, is the SQLite-2 adapter actually considered production ready for our use case?

No, not unless you break up your attachments into smaller pieces and/or sync with a very low batch size. And unfortunately you probably can't use IndexedDB for that much data, because you'll hit the quota limit very quickly, and the Persistent Storage API has not officially shipped yet in any browser.

If I were you, I would probably not use PouchDB, because I would want more fine-grained control over the attachment sizes and how I sync them. I might store md5 sums in PouchDB, but I would not store attachments. Instead, I would sync those separately using AJAX/fetch and then insert the data directly into SQLite Plugin 2, into as small chunks as possible.

stefanhuber commented 8 years ago

I have a similar problem! We are in the process of trying the following approach:

approach 1: PouchDB triggers change events after each document is replicated. Within this event the process of downloading could be done for the files in this document, based on the hash.

approach 2: After the whole pouchDB replication is finished download files.

There are definitely many challenges, e.g.:

csakbalint commented 6 years ago

I had the same problem, PouchDB sync fails silently, when documents are loaded with attachments.

I read the code, and I found out, the problem is with the readAsBinaryString function, more specifically with the FileReader.onloadend function, which wasn't triggered. The solution for this problem was a little bit more obvious and described here:

https://stackoverflow.com/questions/36283445/filereader-not-firing-onloadend-in-ionic-2/43703344

Make sure that polyfills is loaded before cordova!

nolanlawson commented 6 years ago

Closing old issues, please reopen as necessary. Seems this is an issue with ordering of dependencies in user code

knubie commented 2 years ago

Could be related to #46