couchbaselabs / CouchCocoa

Objective-C API for CouchDB on iOS and Mac OS
http://couchbaselabs.github.com/CouchCocoa/docs/
218 stars 66 forks source link

CouchQuery stores error of the last request #32

Closed kaalita closed 12 years ago

kaalita commented 12 years ago

Readonly error property stores the error of the last request.

snej commented 12 years ago

Thanks! Just a few minor issues...

kaalita commented 12 years ago

Updated the code as you suggested. This also includes a fix for another mistake in my original code (after an error occured, the error property was never set to nil again, when subsequent requests were successful).

kaalita commented 12 years ago

Hm, this method works fine with all sorts of failed requests that return at least some kind of response. But I just simulated a request timeout and the error property wasn't changed to the timeout error. It looks like the -operation:willCompleteWithError: implementation in the CouchQuery class isn't called at all, it only calls the -operation:willCompleteWithError: implemention of the CouchResource class.

To catch also the timeout error I could of course move the error property to the CouchResource class, but not sure whether this is the best way to do it.

snej commented 12 years ago

It looks like the -operation:willCompleteWithError: implementation in the CouchQuery class isn't called at all, it only calls the -operation:willCompleteWithError: implemention of the CouchResource class.

Can you explain in more detail? CouchQuery overrides that method, so I don't see a way for the CouchResource implementation to be called without going through the CouchQuery override.

RESTOperation treats HTTP error statuses and socket-level errors the same way; they both call -completedWithError:, which in turn calls the owning resource's -operation:willCompleteWithError:.

kaalita commented 12 years ago

For my test I made all requests to xyz.iriscouch.com time out. I started my app which contains a UITableView with a CouchUITableSource. When I create the CouchLiveQuery with the asLiveQuery method, this happens:

(*) I added comments to all the operation:willCompleteWithError: methods to see which where called and to find out why the error isn't stored in the error property.

snej commented 12 years ago

the method seems to create the CouchLiveQuery synchronously, because it doesn't return until the timeout occurs

I don't think it does — I can't see any place in that code path that will block. And I ran the TouchDB iOS demo and looked at all the calls to -[RESTOperation wait], and none were invoked on a view. Can you pause the app while it's blocked in the synchronous call and show me the backtrace (use the 'bt' debugger command)?

the operation:willCompleteWithError: is called, but not on CouchQuery, but on CouchResource (*)

Please set a breakpoint in the CouchResource method and send me the backtrace when it was hit. I think it must be invoked from the 'super' call in the CouchQuery method.

kaalita commented 12 years ago

To the first point: Oh, you were right, it's not the asLiveQuery method that doesn't return immediately, it's the setQuery method of the CouchUITableSource in the same code line: self.query = [query asLiveQuery];

(lldb) bt

kaalita commented 12 years ago

Please set a breakpoint in the CouchResource method and send me the backtrace when it was hit. I think it must be invoked from the 'super' call in the CouchQuery method.

Sorry, I would, but I can't get that to work :-( I added a symbolic breakpoint for the symbol: [CouchResource operation:willCompleteWithError:] but the breakpoint is never invoked.

I'm already googling for an answer, but until now nothing worked.

kaalita commented 12 years ago

But this hack http://stackoverflow.com/a/9603733 might help out a little bit. I don't know how reliable this is, but at least it gave me now 3 times in a row the same result:

2012-07-03 19:38:12.695 Lingya[24106:11303] Stack = 1 2012-07-03 19:38:12.695 Lingya[24106:11303] Framework = Lingya 2012-07-03 19:38:12.695 Lingya[24106:11303] Memory address = 0x001b4678 2012-07-03 19:38:12.695 Lingya[24106:11303] Class caller = RESTOperation 2012-07-03 19:38:12.696 Lingya[24106:11303] Function caller = completedWithError: 2012-07-03 19:38:12.696 Lingya[24106:11303] Line caller = 920

When a timeout occurs, the method is called from RESTOperation, not from CouchQuery.

snej commented 12 years ago

Re the timeout: your backtrace shows it's coming from setting the tracksChanges property of the database, which CouchUITableSource does so it can listen for changes. (Setting -tracksChanges gets the db's latest sequence number via a synchronous call — this could perhaps be fixed to be async.)

I'll review your pull request again — sorry for the delay, was stuck with a bunch of Couchbase Server tasks this week.