My goal is to send async accelerometer readings to a server in periodic payloads.
Accelerometer data continues while offline and concurrently during the network requests, so I'll need to handle network failures as well as data that arrives during the duration of each network request.
My inelegant approach is to append each new update to an array:
motionManager.startAccelerometerUpdates(to: .main) { data, error in
dataArray.append(data)
}
And then periodically send a group of values to the server (network
is my wrapper around NWPathMonitor()
):
let timer = Timer(fire: Date(), interval: 5, // Every 5 seconds
repeats: true, block: { timer in
if network.connected {
postAccelerometerData(payload: dataArray) { success
if success {
dataArray.removeAll()
}
}
}
})
RunLoop.current.add(timer, forMode: RunLoop.Mode.default)
The major issue with this approach is that the elements of the array added between when the network request fires and when it completes would be removed from the array without ever being sent to the server.
I've had some ideas about adding a queue and dequeuing X elements on for each network request (but then do I add them back to the queue if the request fails?).
I can't help but think there is a better way to approach this using Combine
to "stream" these accelerometer updates to some sort of data structure to buffer them, and then send those on to a server.
The postAccelerometerData()
function just encodes a JSON structure and makes the network request. Nothing particularly special there.