@@ -48,25 +48,40 @@ class DefaultCmabService: CmabService {
4848 let cmabCache : CmabCache
4949 private let logger = OPTLoggerFactory . getLogger ( )
5050
51+ private static let NUM_LOCKS = 1000
52+ private let locks : [ NSLock ]
53+
5154 init ( cmabClient: CmabClient , cmabCache: CmabCache ) {
5255 self . cmabClient = cmabClient
5356 self . cmabCache = cmabCache
57+ self . locks = ( 0 ..< Self . NUM_LOCKS) . map { _ in NSLock ( ) }
58+ }
59+
60+ private func getLockIndex( userId: String , ruleId: String ) -> Int {
61+ let combinedKey = userId + ruleId
62+ let hashValue = MurmurHash3 . hash32 ( key: combinedKey)
63+ let lockIndex = Int ( hashValue) % Self. NUM_LOCKS
64+ return lockIndex
5465 }
5566
5667 func getDecision( config: ProjectConfig ,
5768 userContext: OptimizelyUserContext ,
5869 ruleId: String ,
5970 options: [ OptimizelyDecideOption ] ) -> Result < CmabDecision , Error > {
60- var result : Result < CmabDecision , Error > !
61- let semaphore = DispatchSemaphore ( value: 0 )
62- getDecision ( config: config,
63- userContext: userContext,
64- ruleId: ruleId, options: options) { _result in
65- result = _result
66- semaphore. signal ( )
71+ let lockIdx = getLockIndex ( userId: userContext. userId, ruleId: ruleId)
72+ let lock = locks [ lockIdx]
73+ return lock. withLock {
74+ var result : Result < CmabDecision , Error > !
75+ let semaphore = DispatchSemaphore ( value: 0 )
76+ getDecision ( config: config,
77+ userContext: userContext,
78+ ruleId: ruleId, options: options) { _result in
79+ result = _result
80+ semaphore. signal ( )
81+ }
82+ semaphore. wait ( )
83+ return result
6784 }
68- semaphore. wait ( )
69- return result
7085 }
7186
7287 func getDecision( config: ProjectConfig ,
0 commit comments