NewMultiLocker creates a new MultiLocker instance that manages locks for multiple keys. Keys are deduplicated and sorted lexicographically to ensure consistent lock ordering across all callers, preventing deadlocks. Parameters: - client: A Redis universal client to interact with Redis. - keys: The k
(client redis.UniversalClient, keys []string, value string)
| 180 | // - value: A unique value to associate with all locks (ensures lock ownership). |
| 181 | // Returns a pointer to a new MultiLocker instance. |
| 182 | func NewMultiLocker(client redis.UniversalClient, keys []string, value string) *MultiLocker { |
| 183 | // Deduplicate keys |
| 184 | seen := make(map[string]bool) |
| 185 | uniqueKeys := make([]string, 0, len(keys)) |
| 186 | for _, key := range keys { |
| 187 | if key != "" && !seen[key] { |
| 188 | seen[key] = true |
| 189 | uniqueKeys = append(uniqueKeys, key) |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | // Sort keys lexicographically to ensure consistent ordering |
| 194 | sort.Strings(uniqueKeys) |
| 195 | |
| 196 | // Create lockers for each key |
| 197 | lockers := make([]*Locker, len(uniqueKeys)) |
| 198 | for i, key := range uniqueKeys { |
| 199 | lockers[i] = NewLocker(client, key, value) |
| 200 | } |
| 201 | |
| 202 | return &MultiLocker{ |
| 203 | client: client, |
| 204 | lockers: lockers, |
| 205 | keys: uniqueKeys, |
| 206 | value: value, |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | // Lock attempts to acquire all locks in deterministic order. |
| 211 | // If any lock acquisition fails, all previously acquired locks are released (rollback). |