Added additional notification metadata and rate-limited PN subscriptions

Fixed an issue where the PN subscription API call wasn't taking the frequency rate limit into account
Added the timestamp and expiration timestamp to the notification metadata
This commit is contained in:
Morgan Pretty 2023-09-19 10:15:57 +10:00
parent 67ab1e5194
commit 8b1a4aaba0
2 changed files with 40 additions and 1 deletions

View File

@ -85,7 +85,36 @@ public enum SyncPushTokensJob: JobExecutor {
Logger.info("Re-registering for remote notifications.")
PushRegistrationManager.shared.requestPushTokens()
.flatMap { (pushToken: String, voipToken: String) -> AnyPublisher<Void, Error> in
PushNotificationAPI
/// For our `subscribe` endpoint we only want to call it if:
/// It's been longer than `SyncPushTokensJob.maxFrequency` since the last subscription;
/// The token has changed; or
/// We want to force an update
let timeSinceLastSubscription: TimeInterval = dependencies.dateNow
.timeIntervalSince(
dependencies.standardUserDefaults[.lastPushNotificationSync]
.defaulting(to: Date.distantPast)
)
let uploadOnlyIfStale: Bool? = {
guard
let detailsData: Data = job.details,
let details: Details = try? JSONDecoder().decode(Details.self, from: detailsData)
else { return nil }
return details.uploadOnlyIfStale
}()
guard
timeSinceLastSubscription >= SyncPushTokensJob.maxFrequency ||
dependencies.storage[.lastRecordedPushToken] != pushToken ||
uploadOnlyIfStale == false
else {
SNLog("[SyncPushTokensJob] OS subscription completed, skipping server subscription due to frequency")
return Just(())
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
}
return PushNotificationAPI
.subscribe(
token: Data(hex: pushToken),
isForcedUpdate: true,

View File

@ -8,6 +8,8 @@ extension PushNotificationAPI {
case accountId = "@"
case hash = "#"
case namespace = "n"
case createdTimestampMs = "t"
case expirationTimestampMs = "z"
case dataLength = "l"
case dataTooLong = "B"
}
@ -21,6 +23,12 @@ extension PushNotificationAPI {
/// The swarm namespace in which this message arrived.
let namespace: Int
/// The swarm timestamp when the message was created (unix epoch milliseconds)
let createdTimestampMs: Int64
/// The message's swarm expiry timestamp (unix epoch milliseconds)
let expirationTimestampMs: Int64
/// The length of the message data. This is always included, even if the message content
/// itself was too large to fit into the push notification.
let dataLength: Int
@ -40,6 +48,8 @@ extension PushNotificationAPI.NotificationMetadata {
accountId: try container.decode(String.self, forKey: .accountId),
hash: try container.decode(String.self, forKey: .hash),
namespace: try container.decode(Int.self, forKey: .namespace),
createdTimestampMs: try container.decode(Int64.self, forKey: .createdTimestampMs),
expirationTimestampMs: try container.decode(Int64.self, forKey: .expirationTimestampMs),
dataLength: try container.decode(Int.self, forKey: .dataLength),
dataTooLong: ((try? container.decode(Int.self, forKey: .dataTooLong) != 0) ?? false)
)