CouchDesignDocument stale view cache #40

Open
wants to merge 4 commits into from

2 participants

@pegli

This pull fixes an edge case with querying a view before the view's design document is fetched via replication. Here's what my app is doing:

  1. Start a pull replication with a remote database. The remote database has a design doc named _design/books.
  2. While replication is running, get the design doc with ddoc = [CouchDatabase designDocumentWithName:@"books"]. The ddoc doesn't exist locally yet, so it is created.
  3. Calling [ddoc mapFunctionOfViewNamed:@"by_author"] returns null, but this populates the _views cache in CouchDesignDocument.
  4. Replication finishes and the local design document is saved. In CouchDesignDocument, the _viewsRevisionID and self.currentRevisionID are equal and null, so the view cache is not cleared.
  5. Subsequent calls to mapFunctionOfViewNamed continue to return null even though there is a map function.

If I restart the app at this point, the map function is returned from CouchDesignDocument as expected. I wasn't able to figure out why the currentRevisionID of the design document wasn't updated during the replication process. My workaround was to not cache the views for a design document unless that document has a non-null _viewRevisionID.

This probably hasn't come up before because most people aren't using map and filter functions stored in a design document due to the restriction on downloadable code in an iOS app. My code provides a JavaScript view compiler, so it is important to me to be able to replicate ddoc view functions. Let me know what you think or if you have any alternative suggestions for a workaround. Thanks!

@snej
couchbaselabs member

This isn't the right solution. The fix has two regressions:

  • Before the document exists in the db, every call to -views will return a new empty dictionary, losing any in-memory changes made to views or filters.
  • Multiple assignments to _views, _filters and _viewsRevisionID will leak since the old values aren't released.

Well, rats. I'll go back and try to come up with a non-leaky fix.

@snej
couchbaselabs member

The real issue seems to be why self.currentRevisionID is still nil after the doc gets added to the database by the replicator. The addition of the document should cause -notifyChanged: to be called, which will update the _currentRevisionID.

If you set gCouchLogLevel to 1, you'll get log messages from -notifyChanged: (**** CHANGE #...). You can use this to check whether it's being called on the design document.

@pegli

Got it: notifyChanged: isn't being called because _database.tracksChanges isn't being set to YES in CouchReplication.m. I've reverted the previous change and added the fix to this pull request.

I wasn't sure if tracksChanges should be turned off after replication. The CouchReplication class could potentially save the value when start is called and restore it when replication stops, but from looking at other places where tracksChanges is modified, it seems like the policy is to just leave it on.

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