mixpanel/mixpanel-iphone — pull request #57 by idpaterson (2013-04-11 18:23:37+00:00)
Title: Regression: -flush will not complete upload if called while app is in the background

In previous versions of the Mixpanel API, any flush acquired background task permissions until the upload completed. This allowed the app to call `-flush` from within its own background task with the assurance that the upload would complete. However, currently the background task is only acquired on `-applicationDidEnterBackground:` and therefore a flush triggered by a background task in the app does not complete.

This pull request restores that functionality by testing on any call to `-flush` whether the app is in the background. If it is but a `taskId` has not yet been acquired, the new `-flushInBackgroundTask` is called instead. This method acquires a background task id and performs the upload, after which the background task is ended. The code in `-flushInBackgroundTask` was taken from `-applicationDidEnterBackground:` and the latter updated to call the shared method. Like `-applicationDidEnterBackground:`, `-flushInBackgroundTask` is a no-op if the OS version does not support background tasks.

In our particular use case, we terminate a user's session (i.e. trigger a "Session Ended" event) once the app has been in the background for 30 seconds. The following is a sample debug log before applying this change. Tokens and other unnecessary text were replaced with `[...]`.
```

2013-04-11 14:18:43.127 nt[87388:c07] queueing event: {
event = "Session Ended";
properties = {
[...]
};
}
2013-04-11 14:18:43.128 nt[87388:c07] Mixpanel in background
2013-04-11 14:18:43.128 nt[87388:c07] archiving events data to [...]
2013-04-11 14:18:43.130 nt[87388:c07] flushing data to https://api.mixpanel.com
2013-04-11 14:18:43.131 nt[87388:c07] flushing 1 of 1 queued events: [...]
2013-04-11 14:18:43.131 nt[87388:c07] http request: [...]
2013-04-11 14:18:43.132 nt[87388:c07] no people to flush
```
That actually got farther than I had seen in the past, of course each run is different depending on the timing when the task gets killed. It seemed to have made the request but was killed before anything further could happen. Despite seeming to make the request, the Session Ended event was not recorded in Mixpanel.

After applying the change, the upload completes and the background task is cleaned up.
```
2013-04-11 14:12:43.194 nt[85658:c07] queueing event: {
event = "Session Ended";
properties = {
[...]
};
}
2013-04-11 14:12:43.194 nt[85658:c07] Mixpanel in background
2013-04-11 14:12:43.195 nt[85658:c07] archiving events data to [...]
2013-04-11 14:12:43.197 nt[85658:c07] Mixpanel in background
2013-04-11 14:12:43.198 nt[85658:c07] starting flush background task 3
2013-04-11 14:12:43.198 nt[85658:c07] Mixpanel in background
2013-04-11 14:12:43.199 nt[85658:c07] flushing data to https://api.mixpanel.com
2013-04-11 14:12:43.200 nt[85658:c07] flushing 1 of 1 queued events: [...]
2013-04-11 14:12:43.201 nt[85658:c07] http request: [...]
2013-04-11 14:12:43.202 nt[85658:c07] no people to flush
2013-04-11 14:12:43.520 nt[85658:c07] http status code: 200
2013-04-11 14:12:43.520 nt[85658:c07] http response finished loading
2013-04-11 14:12:43.520 nt[85658:c07] archiving events data to [...]: (
)
2013-04-11 14:12:43.521 nt[85658:c07] ending flush background task 3
```