Skip to content

Commit

Permalink
Run swift format and update the swift format package
Browse files Browse the repository at this point in the history
  • Loading branch information
gazreese committed Sep 19, 2024
1 parent 065fcb6 commit c170427
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 159 deletions.
2 changes: 1 addition & 1 deletion FlagsmithClient/Classes/FlagEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ public struct FlagEvent: Codable, Sendable {
enum CodingKeys: String, CodingKey {
case updatedAt = "updated_at"
}

public let updatedAt: Double
}
5 changes: 2 additions & 3 deletions FlagsmithClient/Classes/Flagsmith+Concurrency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import Foundation

@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *)
public extension Flagsmith {

var flagStreamContinuation: AsyncStream<[Flag]>.Continuation? {
get {
return anyFlagStreamContinuation as? AsyncStream<[Flag]>.Continuation
Expand All @@ -18,13 +17,13 @@ public extension Flagsmith {
anyFlagStreamContinuation = newValue
}
}

var flagStream: AsyncStream<[Flag]> {
AsyncStream { continuation in
anyFlagStreamContinuation = continuation
}
}

/// Get all feature flags (flags and remote config) optionally for a specific identity
///
/// - Parameters:
Expand Down
28 changes: 14 additions & 14 deletions FlagsmithClient/Classes/Flagsmith.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ public final class Flagsmith: @unchecked Sendable {
private let apiManager: APIManager
private let sseManager: SSEManager
private let analytics: FlagsmithAnalytics

// The last time we got flags via the API
private var lastUpdatedAt: Double = 0.0

// The last identity used for fetching flags
private var lastUsedIdentity: String?

var anyFlagStreamContinuation: Any? // AsyncStream<[Flag]>.Continuation? for iOS 13+

/// Base URL
Expand All @@ -36,7 +36,7 @@ public final class Flagsmith: @unchecked Sendable {
get { apiManager.baseURL }
set { apiManager.baseURL = newValue }
}

/// Base `URL` used for the event source.
///
/// The default implementation uses: `https://realtime.flagsmith.com/`.
Expand All @@ -61,7 +61,7 @@ public final class Flagsmith: @unchecked Sendable {
get { analytics.enableAnalytics }
set { analytics.enableAnalytics = newValue }
}

/// Are realtime updates enabled?
public var enableRealtimeUpdates: Bool {
get { sseManager.isStarted }
Expand Down Expand Up @@ -163,12 +163,12 @@ public final class Flagsmith: @unchecked Sendable {
}
}
}

private func handleFlagsError(_ error: any Error, completion: @Sendable @escaping (Result<[Flag], any Error>) -> Void) {
if self.defaultFlags.isEmpty {
if defaultFlags.isEmpty {
completion(.failure(error))
} else {
completion(.success(self.defaultFlags))
completion(.success(defaultFlags))
}
}

Expand Down Expand Up @@ -344,39 +344,39 @@ public final class Flagsmith: @unchecked Sendable {
private func getFlagUsingDefaults(withID id: String, forIdentity _: String? = nil) -> Flag? {
return defaultFlags.first(where: { $0.feature.name == id })
}

private func handleSSEResult(_ result: Result<FlagEvent, any Error>) {
switch result {
case let .success(event):
// Check whether this event is anything new
if lastUpdatedAt < event.updatedAt {
// Evict everything fron the cache
cacheConfig.cache.removeAllCachedResponses()

// Now we can get the new values, which we can emit to the flagUpdateFlow if used
getFeatureFlags(forIdentity: lastUsedIdentity) { result in
switch result {
case let .failure(error):
print("Flagsmith - Error getting flags in SSE stream: \(error.localizedDescription)")

case .success:
// On success the flastream is updated automatically in the API call
print("Flagsmith - Flags updated from SSE stream.")
}
}
}

case let .failure(error):
print("handleSSEResult Error in SSE connection: \(error.localizedDescription)")
}
}

func updateFlagStreamAndLastUpdatedAt(_ flags: [Flag]) {
// Update the flag stream
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
flagStreamContinuation?.yield(flags)
}

// Update the last updated time if the API is giving us newer data
if let apiManagerUpdatedAt = apiManager.lastUpdatedAt, apiManagerUpdatedAt > lastUpdatedAt {
lastUpdatedAt = apiManagerUpdatedAt
Expand Down
5 changes: 2 additions & 3 deletions FlagsmithClient/Classes/Internal/APIManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ final class APIManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
}
}
}

private var _lastUpdatedAt: Double?
var lastUpdatedAt: Double? {
get {
Expand Down Expand Up @@ -81,7 +81,6 @@ final class APIManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
if let error = error {
DispatchQueue.main.async { completion(.failure(FlagsmithError.unhandled(error))) }
} else {

let data = tasksToData[dataTask.taskIdentifier] ?? Data()
DispatchQueue.main.async { completion(.success(data)) }
}
Expand Down Expand Up @@ -197,7 +196,7 @@ final class APIManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
}
}
}

private func updateLastUpdatedFromRequest(_ request: URLRequest) {
// Extract the lastUpdatedAt from the updatedAt header
if let lastUpdatedAt = request.allHTTPHeaderFields?["x-flagsmith-document-updated-at"] {
Expand Down
2 changes: 1 addition & 1 deletion FlagsmithClient/Classes/Internal/ReconnectionDelay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ReconnectionDelay {
private let multiplier: Double

init(initialDelay: TimeInterval = 1.0, maxDelay: TimeInterval = 60.0, multiplier: Double = 2.0) {
self.attempt = 0
attempt = 0
self.initialDelay = initialDelay
self.maxDelay = maxDelay
self.multiplier = multiplier
Expand Down
38 changes: 19 additions & 19 deletions FlagsmithClient/Classes/Internal/SSEManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final class SSEManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
}
}
}

private var _dataTask: URLSessionDataTask?
private var dataTask: URLSessionDataTask? {
get {
Expand All @@ -37,7 +37,7 @@ final class SSEManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
}
}
}

/// Base `URL` used for requests.
private var _baseURL = URL(string: "https://realtime.flagsmith.com/")!
var baseURL: URL {
Expand All @@ -50,7 +50,7 @@ final class SSEManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
}
}
}

/// API Key unique to an organization.
private var _apiKey: String?
var apiKey: String? {
Expand All @@ -63,22 +63,22 @@ final class SSEManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
}
}
}

var isStarted: Bool {
return completionHandler != nil
}

private var completionHandler: CompletionHandler<FlagEvent>?
private let serialAccessQueue = DispatchQueue(label: "sseFlagsmithSerialAccessQueue", qos: .default)
let propertiesSerialAccessQueue = DispatchQueue(label: "ssePropertiesSerialAccessQueue", qos: .default)
private let reconnectionDelay = ReconnectionDelay()

override init() {
super.init()
let configuration = URLSessionConfiguration.default
session = URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
}

// Helper function to process SSE data
internal func processSSEData(_ data: String) {
// Split the data into lines and decode the 'data:' lines from JSON into FlagEvent objects
Expand All @@ -99,24 +99,24 @@ final class SSEManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
}
}
}

// MARK: URLSessionDelegate
func urlSession(_: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {

func urlSession(_: URLSession, dataTask _: URLSessionDataTask, didReceive data: Data) {
serialAccessQueue.sync {
if let message = String(data: data, encoding: .utf8) {
processSSEData(message)
reconnectionDelay.reset()
}
}
}

func urlSession(_: URLSession, task: URLSessionTask, didCompleteWithError error: (any Error)?) {
serialAccessQueue.sync {
if task != dataTask {
return
}

// If the connection times out or we have no error passed to us it's pretty common, so just reconnect
if let error = error {
if let error = error as? URLError, error.code == .timedOut {
Expand All @@ -128,7 +128,7 @@ final class SSEManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
start(completion: self.completionHandler!)
return
}

// Otherwise reconnect with increasing delay using the reconnectionTimer so that we don't load the phone / server
serialAccessQueue.asyncAfter(deadline: .now() + reconnectionDelay.nextDelay()) { [weak self] in
if let self {
Expand All @@ -137,30 +137,30 @@ final class SSEManager: NSObject, URLSessionDataDelegate, @unchecked Sendable {
}
}
}

// MARK: Public Methods

func start(completion: @escaping CompletionHandler<FlagEvent>) {
guard let apiKey = apiKey, !apiKey.isEmpty else {
completion(.failure(FlagsmithError.apiKey))
return
}

guard let completeEventSourceUrl = URL(string: "\(baseURL.absoluteString)sse/environments/\(apiKey)/stream") else {
completion(.failure(FlagsmithError.apiURL("Invalid event source URL")))
return
}

var request = URLRequest(url: completeEventSourceUrl)
request.setValue("text/event-stream, application/json; charset=utf-8", forHTTPHeaderField: "Accept")
request.setValue("no-cache", forHTTPHeaderField: "Cache-Control")
request.setValue("keep-alive", forHTTPHeaderField: "Connection")

completionHandler = completion
dataTask = session.dataTask(with: request)
dataTask?.resume()
}

func stop() {
dataTask?.cancel()
completionHandler = nil
Expand Down
2 changes: 1 addition & 1 deletion FlagsmithClient/Classes/Traits.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public struct Traits: Codable, Sendable {
public let traits: [Trait]
public let identifier: String?
public let flags: [Flag]

init(traits: [Trait], identifier: String?, flags: [Flag] = []) {
self.traits = traits
self.identifier = identifier
Expand Down
Loading

0 comments on commit c170427

Please sign in to comment.