textileio / ios-textile

[DEPRECATED] iOS bindings for https://github.com/textileio/go-textile
MIT License
10 stars 6 forks source link

Handle cafe seesion refresh #61

Open asutula opened 5 years ago

asutula commented 5 years ago

There is currently no handling of an expired client cafe session. This will cause file sync requests to fail and that's the end of the story. I'm imagining we should do something like:

  1. Add a callback to the TextileDelegate protocol that is something like registerCafeWithId:completion:. This will get called in a situation described further down this list.
  2. If a file sync request fails with a 401 unauthorized error, the sdk should attempt to refresh the corresponding cafe session and then un-mark the cafe sync request as pending (so it is returned to the pool of to-be-processed requests).
  3. If the attempt to refresh the cafe session fails because the refresh token is expired, the sdk will call the delegate's registerCafeWithId:completion:. The host app will register the cafe and then call the completion handler passed to it which will un-mark the cafe sync request as pending.
  4. In both those cases, the file sync request will be retried with the updated/valid auth headers the next time the queue is flushed.

Little tricky, but that sounds like a decent solution. Devil is probably in the details. Input appreciated.

Hmm one detail... If there are simultaneous http uploads happening, they could all fail and without some complicated concurrency management, the session would be refreshed multiple times.

asutula commented 5 years ago

@sanderpick would love your thoughts on this today if possible.

asutula commented 5 years ago

That "complicated concurrency management" would be something like:

  1. Request fails with expired session
  2. The request id is added to a list of ids to eventually mark as not pending
  3. Kick off async call to refreshSession (and possibly registerCafeWithId:completion:)
  4. Any other request that fails with expired session while 3. is running is simply added to the list of ids to eventually mark as not pending
  5. Once the session has been refreshed, mark each of the items in the list of ids to as not pending
sanderpick commented 5 years ago

Nice, I like it!

asutula commented 5 years ago

Hey @sanderpick, started work on this an immediately hit a blocker... When a file sync http request fails, I need to refresh the session for the corresponding cafe, but our api to refresh a session takes a peer id. The sdk requests handler class knows nothing about peer id, just http requests and cafe urls. Do we need to add a refreshCafeForUrl method (which will let me refresh the session directly by URL) or maybe cafeForRequestId (which would let me look up the peer id for the failed http request)?

asutula commented 5 years ago

For a minute I thought maybe we could add peerId to CafeHTTPRequest (the thing that gets passed into the callback after writing a request to disk), but that's not ideal because the sdk would have to keep a list of all currently processing CafeHTTPRequests and it would need to be persistent across app launches. Possible, but a big chunk of work for ios and android considering this persistent state already exists in the go-textile layer.

asutula commented 5 years ago

cafeForRequestId is seeming like the best option to me so far.

asutula commented 5 years ago

Took a stab at this here https://github.com/textileio/go-textile/pull/850