From 468ba91a53272864e04d3560e8471f22d74fbc88 Mon Sep 17 00:00:00 2001 From: Matthew Keeler Date: Tue, 20 Feb 2024 14:43:45 -0500 Subject: [PATCH] feat: Add new identify method with time out support A callback provided to the `identify` method may not be executed for a long time under the right circumstances (e.g. the network is slow or unavailable). Customers can now ensure their callbacks will fire within a specified time interval by calling the new `LDClient.identify(context:timeout:completion:)` method. --- LaunchDarkly/LaunchDarkly/LDClient.swift | 32 ++++++++++++++++++- .../LaunchDarkly/Models/IdentifyResult.swift | 6 +++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/LaunchDarkly/LaunchDarkly/LDClient.swift b/LaunchDarkly/LaunchDarkly/LDClient.swift index 677a47a7..2c2e3c16 100644 --- a/LaunchDarkly/LaunchDarkly/LDClient.swift +++ b/LaunchDarkly/LaunchDarkly/LDClient.swift @@ -321,12 +321,42 @@ public class LDClient { } let identifyTask = Task(work: work, sheddable: sheddable) { [self] result in - os_log("%s identity completion with result %s", log: config.logger, type: .debug, typeName(and: #function), String(describing: result)) + os_log("%s identify completed with result %s", log: config.logger, type: .debug, typeName(and: #function), String(describing: result)) completion(IdentifyResult(from: result)) } identifyQueue.enqueue(request: identifyTask) } + /** + Sets the LDContext into the LDClient inline with the behavior detailed on `LDClient.identify(context: completion:)`. Additionally, + this method will ensure the `completion` parameter will be called within the specified time interval. + + Note that the `completion` method being invoked does not mean that the identify request has been cancelled. The identify request will + continue attempting to complete as it would with `LDClient.identify(context: completion:)`. Subsequent identify requests queued behind + a timed out request will remain blocked (or shed) until the in flight request completes. + + - parameter context: The LDContext set with the desired context. + - parameter timeout: The upper time limit before the `completion` callback will be invoked. + - parameter completion: Closure called when the embedded `setOnlineIdentify` call completes, subject to throttling delays. + */ + public func identify(context: LDContext, timeout: TimeInterval, completion: @escaping ((_ result: IdentifyResult) -> Void)) { + var cancel = false + + DispatchQueue.global().asyncAfter(deadline: .now() + timeout) { + guard !cancel else { return } + + cancel = true + completion(.timeout) + } + + identify(context: context) { result in + guard !cancel else { return } + + cancel = true + completion(result) + } + } + func internalIdentify(newContext: LDContext, completion: (() -> Void)? = nil) { var updatedContext = newContext if config.autoEnvAttributes { diff --git a/LaunchDarkly/LaunchDarkly/Models/IdentifyResult.swift b/LaunchDarkly/LaunchDarkly/Models/IdentifyResult.swift index 4cf2d2ee..12075456 100644 --- a/LaunchDarkly/LaunchDarkly/Models/IdentifyResult.swift +++ b/LaunchDarkly/LaunchDarkly/Models/IdentifyResult.swift @@ -13,9 +13,13 @@ public enum IdentifyResult { */ case error /** - The identify request has been replaced with a subsequent request. See `LDClient.identify(context: completion:)` for more details. + The identify request has been replaced with a subsequent request. Read `LDClient.identify(context: completion:)` for more details. */ case shed + /** + The identify request exceeded some time out parameter. Read `LDClient.identify(context: timeout: completion)` for more details. + */ + case timeout init(from: TaskResult) { switch from {