I'm trying to run index updates in a separate service process in Android. Ideally I'd run a sync and then tell my service (using IPC) to slowly update indexes in the service background.
My app is kind of CMS-y, so I'd like to do stale queries and update indexes in a separate service process. Right now loading views (especially after a sync or any process that writes/updates alot) is wicked slow.
We have a minimum of 1300 documents and most times have between 3K and 5K.
I've created an indexing service and am able to load the manager and the database by name but it seems to create some weirdness with the main app. I started by trying just one view - "accounts_by_key_with_name" No problems in the service but the livequery (which I'll probably turn into a normal query) gives me about 20 of the following error:
11-18 00:33:11.959 439-998/com.-----.app W/View﹕ Failed to rebuild view accounts_by_key_with_name. Result code: 500
11-18 00:33:11.959 439-998/com.-----.app E/Query﹕ Exception caught in runAsyncInternal
java.lang.NullPointerException
at com.couchbase.lite.View.updateIndex(View.java:547)
at com.couchbase.lite.Database.queryViewNamed(Database.java:2046)
at com.couchbase.lite.Query$1.run(Query.java:403)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
When I stop querying there and shuffle things around a bit, that error goes away but I get some illegal state exceptions from my indexing service about not being able to load the database. Any thoughts? I can give more code if you'd like.
A top level question, which is probably a "your mileage will vary" type question, will being in a separate process save me that much GC/performance gains in comparison to the headache it saves? Documentation says that managers are threadsafe by default in Android so that could be a quick fix.
Dirty proof of concept code to index in a separate service process:
Database database = mManager.getExistingDatabase(Application.DATABASE_NAME);
mDatabase = mManager.getDatabase(Application.DATABASE_NAME);
Log.d (TAG, "Database created");
mDatabase = mManager.getDatabase(Application.DATABASE_NAME);
Log.d (TAG, "Database loaded");
} catch (CouchbaseLiteException e) {
Log.e(TAG, "Couchbase error", e);
View view = mDatabase.getView("accounts_by_key_with_name");
if(view.getMap() == null) {
Mapper map = new Mapper() {
public void map(Map<String, Object> document, Emitter emitter) {
if ("account".equals(document.get("type"))) {
emitter.emit(document.get("_id"), document.get("name"));
Log.e(TAG, "updated index");
} catch (CouchbaseLiteException e){
Log.e(TAG, "shit went down");