client parameter stats changes

This commit is contained in:
Kyle Matthew Hedden 2022-08-30 17:51:36 -04:00
parent 571d55aebd
commit 55d6df4e25
2 changed files with 32 additions and 35 deletions

View File

@ -7,16 +7,15 @@
// //
@objcMembers open class ClientParameterHandler: NSObject { @objcMembers open class ClientParameterHandler: NSObject {
var parameterHandlerList: [ClientParameterProtocol] = [] static let DefaultTimeout = 30.0
let parametersWorkQueue = DispatchQueue(label: "com.mva.clientparameter")
let group = DispatchGroup()
open func createParametersHandler(_ clientParameterModel: ClientParameterModelProtocol) -> ClientParameterProtocol? { open func createParametersHandler(_ clientParameterModel: ClientParameterModelProtocol) -> ClientParameterProtocol? {
do { do {
let parameterType = try ModelRegistry.getHandler(clientParameterModel) as! ClientParameterProtocol.Type let parameterType = try ModelRegistry.getHandler(clientParameterModel) as! ClientParameterProtocol.Type
return parameterType.init(clientParameterModel) return parameterType.init(clientParameterModel)
} catch { } catch {
MVMCoreLoggingHandler.shared()?.logCoreEvent(.clientParameterNotFound(name: clientParameterModel.type))
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: #function) { if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: #function) {
MVMCoreLoggingHandler.addError(toLog: errorObject) MVMCoreLoggingHandler.addError(toLog: errorObject)
} }
@ -52,29 +51,29 @@
} }
open func getParameters(with model: ClientParameterModel, requestParameters: [String: Any], completionHandler:@escaping ([String: Any]?) -> ()) throws { open func getParameters(with model: ClientParameterModel, requestParameters: [String: Any], completionHandler:@escaping ([String: Any]?) -> ()) throws {
let timeout = model.timeout ?? 30.0 let parametersWorkQueue = DispatchQueue(label: "com.mva.clientparameter")
let group = DispatchGroup()
let timeout = model.timeout ?? Self.DefaultTimeout
let parameterHandlerList = model.list.compactMap { createParametersHandler($0) }
let requestUUID = [0..<parameterHandlerList.count].map { _ in UUID().uuidString }
var returnedList = [[String: AnyHashable]?](repeating: nil, count: parameterHandlerList.count)
// Dispatch setup on queue to ensure setup is complete before completion callbacks. // Dispatch setup on queue to ensure setup is complete before completion callbacks.
// Don't use [weak self]. Object is deallocated in the dispatch queue. // Don't use [weak self]. Object is deallocated in the dispatch queue.
parametersWorkQueue.async(group: group, qos: .userInitiated) { parametersWorkQueue.async(group: group, qos: .userInitiated) {
// Create the handler list so that same object can be used when merging. Merging needs default value in case of timeout
for parameterModel in model.list {
if let parameterHandler = self.createParametersHandler(parameterModel) {
self.parameterHandlerList.append(parameterHandler)
}
}
var returnedList = [[String: AnyHashable]?](repeating: nil, count: self.parameterHandlerList.count)
var mergedParametersList: [String: AnyHashable] { var mergedParametersList: [String: AnyHashable] {
var parametersList: [String: AnyHashable] = [:] return returnedList.enumerated().map { (index, element) -> [String: AnyHashable] in
for (index, item) in returnedList.enumerated() { guard let parameter = element else {
let parameter = item ?? self.parameterHandlerList[index].valueOnTimeout() MVMCoreLoggingHandler.shared()?.logCoreEvent(.clientParameterTimeout(name: model.list[index].type, uuid: requestUUID[index]))
parametersList = parametersList.merging(parameter) { (_, new) in new } return parameterHandlerList[index].valueOnTimeout()
}
return parameter
}.reduce(into: [String: AnyHashable]()) { partialResult, next in
partialResult.merge(next) { first, last in first }
} }
return parametersList
} }
// Setup completion handlers. Barriered to ensure one happens after the other. // Setup completion handlers. Barriered to ensure one happens after the other.
@ -92,28 +91,30 @@
} }
// Setup timeout. // Setup timeout.
self.parametersWorkQueue.asyncAfter(deadline: .now() + .seconds(Int(timeout)), execute: timeoutWorkItem) parametersWorkQueue.asyncAfter(deadline: .now() + .seconds(Int(timeout)), execute: timeoutWorkItem)
// Setup the parameter execution. // Setup the parameter execution.
for (index, parameterHandler) in self.parameterHandlerList.enumerated() { for (index, parameterHandler) in parameterHandlerList.enumerated() {
let parameterType = parameterHandler.clientParameterModel.type let parameterType = parameterHandler.clientParameterModel.type
self.group.enter() MVMCoreLoggingHandler.shared()?.logCoreEvent(.clientParameterFetching(name: parameterType, uuid: requestUUID[index]))
group.enter()
parameterHandler.fetchClientParameters(requestParameters: requestParameters, parameterHandler.fetchClientParameters(requestParameters: requestParameters,
timingOutIn: timeout) { (receivedParameter) in timingOutIn: timeout) { (receivedParameter) in
// Queue the results for merge. // Queue the results for merge.
self.parametersWorkQueue.async { parametersWorkQueue.async {
if (returnedList[index] != nil) { if (returnedList[index] != nil) {
MVMCoreLoggingHandler.addError(toLog: MVMCoreErrorObject(title: nil, message: "Client parameter \(parameterType) has already executed. The completion handler should only be called once!", code: ErrorCode.default.rawValue, domain: ErrorDomainNative, location: String(describing: ClientParameterHandler.self))!) MVMCoreLoggingHandler.addError(toLog: MVMCoreErrorObject(title: nil, message: "Client parameter \(parameterType) has already executed. The completion handler should only be called once!", code: ErrorCode.default.rawValue, domain: ErrorDomainNative, location: String(describing: ClientParameterHandler.self))!)
} else { } else {
MVMCoreLoggingHandler.shared()?.logCoreEvent(.clientParameterFetchComplete(name: parameterType, uuid: requestUUID[index]))
returnedList[index] = receivedParameter returnedList[index] = receivedParameter
self.group.leave() // Leaving is only done after setup (barriered). group.leave() // Leaving is only done after setup (barriered).
} }
} }
} }
} }
// Callback when all parameters have been merged. // Callback when all parameters have been merged.
self.group.notify(queue: self.parametersWorkQueue, work: completionWorkItem); group.notify(queue: parametersWorkQueue, work: completionWorkItem);
} }
} }
} }

View File

@ -56,28 +56,24 @@ public enum MVMCoreEvent {
/// Could not find the client parameter specified. /// Could not find the client parameter specified.
case clientParameterNotFound( case clientParameterNotFound(
name: String, name: String
pageType: String
) )
/// The client perameter handler was invoked and is in progress. /// The client perameter handler was invoked and is in progress.
case clientParameterFetching( case clientParameterFetching(
name: String, name: String,
pageType: String,
uuid: String uuid: String
) )
/// The client perameter handler timed out and is returning a default value. /// The client perameter handler timed out and is returning a default value.
case clientParameterTimeout( case clientParameterTimeout(
name: String, name: String,
pageType: String,
uuid: String uuid: String
) )
/// The client paramter fetch completed. /// The client paramter fetch completed.
case clientParameterComplete( case clientParameterFetchComplete(
name: String, name: String,
pageType: String,
uuid: String uuid: String
) )
@ -100,7 +96,7 @@ public enum MVMCoreEvent {
case .clientParameterNotFound: return .clientParameter case .clientParameterNotFound: return .clientParameter
case .clientParameterFetching: return .clientParameter case .clientParameterFetching: return .clientParameter
case .clientParameterTimeout: return .clientParameter case .clientParameterTimeout: return .clientParameter
case .clientParameterComplete: return .clientParameter case .clientParameterFetchComplete: return .clientParameter
} }
} }