From 4805c1ed43fe21bfb7098e0621b9c43e959b40de Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Tue, 12 Jan 2021 16:36:09 -0500 Subject: [PATCH] polish, re-enable timeout --- .../ActionHandler+ClientParameters.swift | 6 -- .../ActionType/ActionOpenPageModel.swift | 2 +- .../ActionType/ActionOpenUrlModel.swift | 2 +- .../ClientParameterActionProtocol.swift | 2 +- .../ClientParameterModelProtocol.swift | 1 - .../ClientParameterProtocol.swift | 2 +- .../ClientParameterRegistry.swift | 89 +++++++++++-------- 7 files changed, 56 insertions(+), 48 deletions(-) diff --git a/MVMCore/MVMCore/ActionHandling/ActionHandler+ClientParameters.swift b/MVMCore/MVMCore/ActionHandling/ActionHandler+ClientParameters.swift index 53acc76..fe52f39 100644 --- a/MVMCore/MVMCore/ActionHandling/ActionHandler+ClientParameters.swift +++ b/MVMCore/MVMCore/ActionHandling/ActionHandler+ClientParameters.swift @@ -8,12 +8,6 @@ import Foundation -//- (void)handleActionWithDictionary:(nullable NSDictionary *)dictionary additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject *)delegate { -// -// NSString *action = [dictionary stringForKey:KeyActionType]; -// [self handleAction:action actionInformation:dictionary additionalData:additionalData delegate:delegate]; -//} - public extension MVMCoreActionHandler { @objc func setClientParameter(with actionMap: [String: Any]?, completionHandler: @escaping ([String : Any]?) -> ()) { diff --git a/MVMCore/MVMCore/Models/ActionType/ActionOpenPageModel.swift b/MVMCore/MVMCore/Models/ActionType/ActionOpenPageModel.swift index 52af9f0..a20d343 100644 --- a/MVMCore/MVMCore/Models/ActionType/ActionOpenPageModel.swift +++ b/MVMCore/MVMCore/Models/ActionType/ActionOpenPageModel.swift @@ -20,7 +20,7 @@ public var presentationStyle: String? public var tabBarIndex: Int? public var background: Bool? - public var clientParameterModel: ClientParameterModel? + public var clientParameters: ClientParameterModel? //-------------------------------------------------- // MARK: - Initialzier diff --git a/MVMCore/MVMCore/Models/ActionType/ActionOpenUrlModel.swift b/MVMCore/MVMCore/Models/ActionType/ActionOpenUrlModel.swift index 998716b..96e51f5 100644 --- a/MVMCore/MVMCore/Models/ActionType/ActionOpenUrlModel.swift +++ b/MVMCore/MVMCore/Models/ActionType/ActionOpenUrlModel.swift @@ -18,6 +18,7 @@ public var browserUrl: String public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? + public var clientParameters: ClientParameterModel? public var appURL: String? //TODO: Should be removed in future releases. This should be MF specific. @@ -30,7 +31,6 @@ public var dontShowProgress: Bool? public var headerParameters: JSONValueDictionary? public var enableNativeScroll: Bool? - public var clientParameterModel: ClientParameterModel? //-------------------------------------------------- // MARK: - Initialzier diff --git a/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterActionProtocol.swift b/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterActionProtocol.swift index 51fb71a..f969a95 100644 --- a/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterActionProtocol.swift +++ b/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterActionProtocol.swift @@ -9,5 +9,5 @@ import Foundation public protocol ClientParameterActionProtocol { - var clientParameterModel: ClientParameterModel? { get set } + var clientParameters: ClientParameterModel? { get set } } diff --git a/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterModelProtocol.swift b/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterModelProtocol.swift index 2dd6731..b742170 100644 --- a/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterModelProtocol.swift +++ b/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterModelProtocol.swift @@ -10,7 +10,6 @@ import Foundation public protocol ClientParameterModelProtocol: ModelProtocol { var type: String { get } - var inputParameters: JSONValueDictionary? { get set } } public extension ClientParameterModelProtocol { diff --git a/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterProtocol.swift b/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterProtocol.swift index 53dd12d..3420cf9 100644 --- a/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterProtocol.swift +++ b/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterProtocol.swift @@ -11,7 +11,7 @@ import Foundation public protocol ClientParameterProtocol { init() static var name: String { get } - func clientParameter(with paramModel: ClientParameterModelProtocol, _ timout: CGFloat?, completionHandler:@escaping ([String: Any]?) -> ()) + func fetchClientParameters(for paramModel: ClientParameterModelProtocol, timingOutIn timeout: Double, completionHandler:@escaping ([String: Any]?) -> ()) } extension ClientParameterProtocol { diff --git a/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterRegistry.swift b/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterRegistry.swift index cc98d1a..7cdcefa 100644 --- a/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterRegistry.swift +++ b/MVMCore/MVMCore/Models/ActionType/Client Parameters/ClientParameterRegistry.swift @@ -14,11 +14,11 @@ import Foundation public static let shared = ClientParameterRegistry() private var mapping: [String: ClientParameterProtocol.Type] = [:] - public func register(param: T.Type) { - mapping[T.name] = param + public func register(_ handler: T.Type) { + mapping[T.name] = handler } - public func createParam(_ actionType: String) -> ClientParameterProtocol? { + public func createParamHandler(_ actionType: String) -> ClientParameterProtocol? { guard let patamType = mapping[actionType] else { return nil } return patamType.init() } @@ -34,58 +34,73 @@ import Foundation } var paramsList: [String: Any] = [:] - - DispatchQueue.global(qos: .userInitiated).async { - - let timeout = clientParameters.optionalCGFloatForKey("timeout") ?? 30.0 - - let concurrentQueue = DispatchQueue(label: "com.mva.clientparam", attributes: .concurrent) - let group = DispatchGroup() - - - let completionItem = DispatchWorkItem { + let timeout = clientParameters["timeout"] as? Double ?? 30.0 + + let parametersWorkQueue = DispatchQueue(label: "com.mva.clientparam") + let group = DispatchGroup() + let defaultErrorString = "Failed to collect." + + // Dispatch setup on queue to ensure setup is complete before completion callbacks. + parametersWorkQueue.async(group: group, qos: .userInitiated) { + // Setup completion handlers. Barriered to ensure one happens after the other. + var complete = false + let timeoutWorkItem = DispatchWorkItem(qos: .userInitiated) { completionHandler(paramsList); + complete = true } - -// let dispatchAfterTime = DispatchTimeInterval.seconds(Int(timeout)) -// concurrentQueue.asyncAfter(deadline: .now() + dispatchAfterTime, execute: completionItem) - + let completionWorkItem = DispatchWorkItem(qos: .userInitiated) { + timeoutWorkItem.cancel() + if !complete { // In the case of firing after timeout. + completionHandler(paramsList); + complete = true + } + } + + // Setup timeout. + parametersWorkQueue.asyncAfter(deadline: .now() + .seconds(Int(timeout)), execute: timeoutWorkItem) + + // Setup the parameter execution. for param in paramsModelList { - group.enter() - - clientParameterRegistry.injectParam(param, timeout-1) { (clientParam) in - guard let clientParam = clientParam else { - group.leave() - return + guard let paramModel = try? Self.getModel(param) else { + if let paramType = param.optionalStringForKey("type") { + paramsList[paramType] = ["error": "Parsing error."] } - concurrentQueue.async(flags: .barrier) { - paramsList.merge(clientParam) { (_, new) in new } - group.leave() + continue + } + // Setup default timeout / nil error. This will be replaced as parameters are collected. + paramsList[paramModel.type] = ["error": defaultErrorString] + group.enter() + // Dispatch asynchronous injection. + clientParameterRegistry.injectParam(paramModel, before: timeout) { (clientParam) in + // Queue the results for merge. + parametersWorkQueue.async { + if let clientParam = clientParam { + paramsList[paramModel.type] = clientParam + } + group.leave() // Leaving is only done after setup (barriered). } } } - group.notify(queue: concurrentQueue, work: completionItem); + + // Callback when all parameters have been merged. + group.notify(queue: parametersWorkQueue, work: completionWorkItem); } } - func injectParam( _ param: [String: Any], _ timout: CGFloat, completionHandler:@escaping ([String: Any]?) -> ()) { - - guard let paramModel = try? ClientParameterRegistry.getModel(param), - let param = ClientParameterRegistry.shared.createParam(paramModel.type) else { + func injectParam( _ paramModel: ClientParameterModelProtocol, before timeout: Double, completionHandler:@escaping ([String: Any]?) -> ()) { + guard let paramHandler = ClientParameterRegistry.shared.createParamHandler(paramModel.type) else { return completionHandler(nil) } - - param.clientParameter(with: paramModel, timout, completionHandler: completionHandler) + paramHandler.fetchClientParameters(for: paramModel, timingOutIn: timeout, completionHandler: completionHandler) } - /// Add all registry here. public static func registerParameters() { } /// Register Default Core Bridge Objects - public static func register(parameter: T.Type, type: M.Type) { - try? ModelRegistry.register(type) - ClientParameterRegistry.shared.register(param: parameter) + public static func register(handler: T.Type, for model: M.Type) { + try? ModelRegistry.register(model) + ClientParameterRegistry.shared.register(handler) } public static func getModel(_ json: [String: Any]) throws -> ClientParameterModelProtocol {