Skip to content

Commit

Permalink
feat: use new header to set polling interval (#519)
Browse files Browse the repository at this point in the history
Co-authored-by: Levi Bostian <levi@customer.io>
  • Loading branch information
BernardGatt and levibostian committed Feb 15, 2024
1 parent cdf2f1f commit 05a1ebd
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 12 deletions.
4 changes: 2 additions & 2 deletions Sources/MessagingInApp/Gist/Gist.swift
Expand Up @@ -2,9 +2,9 @@ import Foundation
import UIKit

public class Gist: GistDelegate {
private var messageQueueManager = MessageQueueManager()
private var messageManagers: [MessageManager] = []
var messageQueueManager = MessageQueueManager()
var shownMessageQueueIds: Set<String> = []
private var messageManagers: [MessageManager] = []
public var siteId: String = ""
public var dataCenter: String = ""

Expand Down
20 changes: 14 additions & 6 deletions Sources/MessagingInApp/Gist/Managers/MessageQueueManager.swift
Expand Up @@ -2,23 +2,26 @@ import Foundation
import UIKit

class MessageQueueManager {
var interval: Double = 600
private var queueTimer: Timer!
// The local message store is used to keep messages that can't be displayed because the route rule doesnt match.
private var localMessageStore: [String: Message] = [:]

func setup() {
func setup(skipQueueCheck: Bool = false) {
queueTimer = Timer.scheduledTimer(
timeInterval: 10,
timeInterval: interval,
target: self,
selector: #selector(fetchUserMessages),
userInfo: nil,
repeats: true
)

// Since on app launch there's a short period where the applicationState is still set to "background"
// We wait 1 second for the app to become active before checking for messages.
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.fetchUserMessages()
if !skipQueueCheck {
// Since on app launch there's a short period where the applicationState is still set to "background"
// We wait 1 second for the app to become active before checking for messages.
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.fetchUserMessages()
}
}
}

Expand Down Expand Up @@ -68,7 +71,12 @@ class MessageQueueManager {
QueueManager(siteId: Gist.shared.siteId, dataCenter: Gist.shared.dataCenter)
.fetchUserQueue(userToken: userToken, completionHandler: { response in
switch response {
case .success(nil):
Logger.instance.info(message: "No changes to remote queue")
case .success(let responses):
guard let responses else {
return
}
// To prevent us from showing expired / revoked messages, clear user messages from local queue.
self.clearUserMessagesFromLocalStore()
Logger.instance.info(message: "Gist queue service found \(responses.count) new messages")
Expand Down
23 changes: 20 additions & 3 deletions Sources/MessagingInApp/Gist/Managers/QueueManager.swift
Expand Up @@ -9,15 +9,20 @@ class QueueManager {
self.dataCenter = dataCenter
}

func fetchUserQueue(userToken: String, completionHandler: @escaping (Result<[UserQueueResponse], Error>) -> Void) {
func fetchUserQueue(userToken: String, completionHandler: @escaping (Result<[UserQueueResponse]?, Error>) -> Void) {
do {
try GistQueueNetwork(siteId: siteId, dataCenter: dataCenter, userToken: userToken)
.request(QueueEndpoint.getUserQueue, completionHandler: { response in
switch response {
case .success(let (data, response)):
if response.statusCode == 204 {
self.updatePollingInterval(headers: response.allHeaderFields)
switch response.statusCode {
case 204:
completionHandler(.success([]))
} else {
case 304:
// No changes to the remote queue, returning nil so we don't clear local store.
completionHandler(.success(nil))
default:
do {
var userQueue = [UserQueueResponse]()
if let userQueueResponse =
Expand Down Expand Up @@ -46,4 +51,16 @@ class QueueManager {
completionHandler(.failure(error))
}
}

private func updatePollingInterval(headers: [AnyHashable: Any]) {
if let newPollingIntervalString = headers["x-gist-queue-polling-interval"] as? String,
let newPollingInterval = Double(newPollingIntervalString),
newPollingInterval != Gist.shared.messageQueueManager.interval {
DispatchQueue.main.async {
Gist.shared.messageQueueManager.interval = newPollingInterval
Gist.shared.messageQueueManager.setup(skipQueueCheck: true)
Logger.instance.info(message: "Polling interval changed to: \(newPollingInterval) seconds")
}
}
}
}
3 changes: 2 additions & 1 deletion Sources/MessagingInApp/Gist/Network/BaseNetwork.swift
Expand Up @@ -15,6 +15,7 @@ enum BaseNetwork {
completionHandler: @escaping (Result<GistNetworkResponse, Error>) -> Void
) throws {
var urlRequest = urlRequest
urlRequest.cachePolicy = .reloadIgnoringCacheData
switch request.parameters {
case .body(let body):
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: body.asDictionary(), options: [])
Expand All @@ -31,7 +32,7 @@ enum BaseNetwork {
URLSession.shared.dataTask(with: urlRequest, completionHandler: { data, response, error in
if let error = error { completionHandler(.failure(error)) }
guard let data = data, let response = response as? HTTPURLResponse,
(200 ... 299).contains(response.statusCode)
(200 ... 304).contains(response.statusCode)
else {
completionHandler(.failure(GistNetworkError.serverError))
return
Expand Down

0 comments on commit 05a1ebd

Please sign in to comment.