diff --git a/Sources/CMAB/CmabService.swift b/Sources/CMAB/CmabService.swift index c74205e8..20c33f82 100644 --- a/Sources/CMAB/CmabService.swift +++ b/Sources/CMAB/CmabService.swift @@ -48,25 +48,40 @@ class DefaultCmabService: CmabService { private let cmabCache: LruCache private let logger = OPTLoggerFactory.getLogger() + private static let NUM_LOCKS = 1000 + private let locks: [NSLock] + init(cmabClient: CmabClient, cmabCache: LruCache) { self.cmabClient = cmabClient self.cmabCache = cmabCache + self.locks = (0.. Int { + let combinedKey = userId + ruleId + let hashValue = MurmurHash3.hash32(key: combinedKey) + let lockIndex = Int(hashValue) % Self.NUM_LOCKS + return lockIndex } func getDecision(config: ProjectConfig, userContext: OptimizelyUserContext, ruleId: String, options: [OptimizelyDecideOption]) -> Result { - var result: Result! - let semaphore = DispatchSemaphore(value: 0) - getDecision(config: config, - userContext: userContext, - ruleId: ruleId, options: options) { _result in - result = _result - semaphore.signal() + let lockIdx = getLockIndex(userId: userContext.userId, ruleId: ruleId) + let lock = locks[lockIdx] + return lock.withLock { + var result: Result! + let semaphore = DispatchSemaphore(value: 0) + getDecision(config: config, + userContext: userContext, + ruleId: ruleId, options: options) { _result in + result = _result + semaphore.signal() + } + semaphore.wait() + return result } - semaphore.wait() - return result } func getDecision(config: ProjectConfig,