Added FCMError to make handling specific errors easier
Many thanks to @grahamburgsma
So, now we can parse Google and FCM errors, let's take a look how
return try fcm.sendMessage(container.make(Client.self), message: message).transform(to: ()).catchFlatMap { error in
guard let googleError = error as? GoogleError, let fcmError = googleError.fcmError else {
return container.eventLoop.newFailedFuture(error: error)
}
switch fcmError.errorCode {
case .unspecified: break
case .invalid: break
case .unregistered: break
case .senderIDMismatch: break
case .quotaExceeded: break
case .apnsAuth: break
case .unavailable: break
case .internal: break
}
}
And now we can delete token if we're getting unregistered
error like this:
return try fcm.sendMessage(container.make(Client.self), message: message).transform(to: ()).catchFlatMap { error in
guard let googleError = error as? GoogleError, let fcmError = googleError.fcmError else {
return container.eventLoop.newSucceededFuture(result: ())
}
switch fcmError.errorCode {
case .unregistered: // drop token only if unregistered
return container.requestPooledConnection(to: .psql).flatMap { conn in
return Self.query(on: conn).filter(\.firebaseToken == token).first().flatMap { model in
defer { try? container.releasePooledConnection(conn, to: .psql) }
guard var model = model else { return container.eventLoop.newSucceededFuture(result: ()) }
model.firebaseToken = nil
return model.save(on: conn).transform(to: ())
}.always {
try? container.releasePooledConnection(conn, to: .psql)
}
}
default:
return container.eventLoop.newSucceededFuture(result: ())
}
}