polish, re-enable timeout

This commit is contained in:
Kyle Matthew Hedden 2021-01-12 16:36:09 -05:00
parent 2bfca1cfcd
commit 4805c1ed43
7 changed files with 56 additions and 48 deletions

View File

@ -8,12 +8,6 @@
import Foundation import Foundation
//- (void)handleActionWithDictionary:(nullable NSDictionary *)dictionary additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject <MVMCoreLoadDelegateProtocol, MVMCorePresentationDelegateProtocol,MVMCoreActionDelegateProtocol>*)delegate {
//
// NSString *action = [dictionary stringForKey:KeyActionType];
// [self handleAction:action actionInformation:dictionary additionalData:additionalData delegate:delegate];
//}
public extension MVMCoreActionHandler { public extension MVMCoreActionHandler {
@objc func setClientParameter(with actionMap: [String: Any]?, completionHandler: @escaping ([String : Any]?) -> ()) { @objc func setClientParameter(with actionMap: [String: Any]?, completionHandler: @escaping ([String : Any]?) -> ()) {

View File

@ -20,7 +20,7 @@
public var presentationStyle: String? public var presentationStyle: String?
public var tabBarIndex: Int? public var tabBarIndex: Int?
public var background: Bool? public var background: Bool?
public var clientParameterModel: ClientParameterModel? public var clientParameters: ClientParameterModel?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initialzier // MARK: - Initialzier

View File

@ -18,6 +18,7 @@
public var browserUrl: String public var browserUrl: String
public var extraParameters: JSONValueDictionary? public var extraParameters: JSONValueDictionary?
public var analyticsData: JSONValueDictionary? public var analyticsData: JSONValueDictionary?
public var clientParameters: ClientParameterModel?
public var appURL: String? public var appURL: String?
//TODO: Should be removed in future releases. This should be MF specific. //TODO: Should be removed in future releases. This should be MF specific.
@ -30,7 +31,6 @@
public var dontShowProgress: Bool? public var dontShowProgress: Bool?
public var headerParameters: JSONValueDictionary? public var headerParameters: JSONValueDictionary?
public var enableNativeScroll: Bool? public var enableNativeScroll: Bool?
public var clientParameterModel: ClientParameterModel?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initialzier // MARK: - Initialzier

View File

@ -9,5 +9,5 @@
import Foundation import Foundation
public protocol ClientParameterActionProtocol { public protocol ClientParameterActionProtocol {
var clientParameterModel: ClientParameterModel? { get set } var clientParameters: ClientParameterModel? { get set }
} }

View File

@ -10,7 +10,6 @@ import Foundation
public protocol ClientParameterModelProtocol: ModelProtocol { public protocol ClientParameterModelProtocol: ModelProtocol {
var type: String { get } var type: String { get }
var inputParameters: JSONValueDictionary? { get set }
} }
public extension ClientParameterModelProtocol { public extension ClientParameterModelProtocol {

View File

@ -11,7 +11,7 @@ import Foundation
public protocol ClientParameterProtocol { public protocol ClientParameterProtocol {
init() init()
static var name: String { get } 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 { extension ClientParameterProtocol {

View File

@ -14,11 +14,11 @@ import Foundation
public static let shared = ClientParameterRegistry() public static let shared = ClientParameterRegistry()
private var mapping: [String: ClientParameterProtocol.Type] = [:] private var mapping: [String: ClientParameterProtocol.Type] = [:]
public func register<T:ClientParameterProtocol>(param: T.Type) { public func register<T:ClientParameterProtocol>(_ handler: T.Type) {
mapping[T.name] = param mapping[T.name] = handler
} }
public func createParam(_ actionType: String) -> ClientParameterProtocol? { public func createParamHandler(_ actionType: String) -> ClientParameterProtocol? {
guard let patamType = mapping[actionType] else { return nil } guard let patamType = mapping[actionType] else { return nil }
return patamType.init() return patamType.init()
} }
@ -34,58 +34,73 @@ import Foundation
} }
var paramsList: [String: Any] = [:] var paramsList: [String: Any] = [:]
let timeout = clientParameters["timeout"] as? Double ?? 30.0
DispatchQueue.global(qos: .userInitiated).async {
let parametersWorkQueue = DispatchQueue(label: "com.mva.clientparam")
let timeout = clientParameters.optionalCGFloatForKey("timeout") ?? 30.0 let group = DispatchGroup()
let defaultErrorString = "Failed to collect."
let concurrentQueue = DispatchQueue(label: "com.mva.clientparam", attributes: .concurrent)
let group = DispatchGroup() // 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.
let completionItem = DispatchWorkItem { var complete = false
let timeoutWorkItem = DispatchWorkItem(qos: .userInitiated) {
completionHandler(paramsList); completionHandler(paramsList);
complete = true
} }
let completionWorkItem = DispatchWorkItem(qos: .userInitiated) {
// let dispatchAfterTime = DispatchTimeInterval.seconds(Int(timeout)) timeoutWorkItem.cancel()
// concurrentQueue.asyncAfter(deadline: .now() + dispatchAfterTime, execute: completionItem) 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 { for param in paramsModelList {
group.enter() guard let paramModel = try? Self.getModel(param) else {
if let paramType = param.optionalStringForKey("type") {
clientParameterRegistry.injectParam(param, timeout-1) { (clientParam) in paramsList[paramType] = ["error": "Parsing error."]
guard let clientParam = clientParam else {
group.leave()
return
} }
concurrentQueue.async(flags: .barrier) { continue
paramsList.merge(clientParam) { (_, new) in new } }
group.leave() // 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]?) -> ()) { func injectParam( _ paramModel: ClientParameterModelProtocol, before timeout: Double, completionHandler:@escaping ([String: Any]?) -> ()) {
guard let paramHandler = ClientParameterRegistry.shared.createParamHandler(paramModel.type) else {
guard let paramModel = try? ClientParameterRegistry.getModel(param),
let param = ClientParameterRegistry.shared.createParam(paramModel.type) else {
return completionHandler(nil) return completionHandler(nil)
} }
paramHandler.fetchClientParameters(for: paramModel, timingOutIn: timeout, completionHandler: completionHandler)
param.clientParameter(with: paramModel, timout, completionHandler: completionHandler)
} }
/// Add all registry here. /// Add all registry here.
public static func registerParameters() { } public static func registerParameters() { }
/// Register Default Core Bridge Objects /// Register Default Core Bridge Objects
public static func register<T:ClientParameterProtocol, M: ModelProtocol>(parameter: T.Type, type: M.Type) { public static func register<T:ClientParameterProtocol, M: ModelProtocol>(handler: T.Type, for model: M.Type) {
try? ModelRegistry.register(type) try? ModelRegistry.register(model)
ClientParameterRegistry.shared.register(param: parameter) ClientParameterRegistry.shared.register(handler)
} }
public static func getModel(_ json: [String: Any]) throws -> ClientParameterModelProtocol { public static func getModel(_ json: [String: Any]) throws -> ClientParameterModelProtocol {