private struct Flags: Decodable {
let flags: [Flag]
}
private struct Flag: Decodable {
let key: String
let enabled: Bool
}
public class FeatureFlagClient {
private static var endpoint: URL?
private static var flags: Flags?
public static func configure(withEndpoint endpoint: String, refreshRate: TimeInterval = 300) {
guard let endpointURL = URL(string: endpoint) else {
print("Endoint: \(endpoint) is invalid.")
return
}
self.endpoint = endpointURL
self.fetchAllFlags()
Timer.scheduledTimer(withTimeInterval: refreshRate, repeats: true) { _ in
self.fetchAllFlags()
}
}
private static func fetchAllFlags() {
guard let endpoint = self.endpoint else {
print("Unable to fetch feature flags. Error: Unknown reason.")
return
}
var urlRequest = URLRequest(url: endpoint)
urlRequest.httpMethod = "GET"
let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if let error = error {
print("Unable to fetch feature flags. Error: \(error.localizedDescription)")
return
}
guard let data = data else {
print("Unable to fetch feature flags. Error: Unknown reason.")
return
}
let decoder = JSONDecoder()
do {
flags = try decoder.decode(Flags.self, from: data)
NotificationCenter.default.post(Notification(name: Notification.Name.FeatureFlagsUpdated))
} catch {
print("Unable to fetch feature flags. Error: \(error.localizedDescription).")
return
}
}
dataTask.resume()
}
public static func isFlagEnabled(_ key: String) -> Bool {
let flag = self.flags?.flags.first(where: {$0.key == key})
return flag?.enabled ?? false
}
}
public extension Notification.Name {
static let FeatureFlagsUpdated = Notification.Name("featureFlagsUpdated")
}