P1.1: per-queue блокировки вместо глобального лока на операции с очередью
Все операции с содержимым очереди (send/receive/delete/visibility/purge/attributes/ tags/admin/gauge/tick) переведены на per-queue RWMutex (QueueStore.GetLocked/ GetRLocked + queue.LockMu). Глобальный SyncQueues-лок остался только для map и неизменяемых полей. DLQ-переносы берут лок DLQ отдельно (порядок main→DLQ). marshalQueueMeta больше не мутирует очередь (DTO-снапшот). Устранён дедлок create_queue (setQueueAttributesV1 вызывается вне глобального лока). Добавлены конкурентные тесты; go test -race зелёный. Снимает боттлнек: синхронный Redis-I/O больше не держит глобальный лок.
This commit is contained in:
@@ -74,6 +74,31 @@ func (s *QueueStore) RemoveQueue(key string) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetLocked — возвращает очередь с захваченной per-queue write-блокировкой.
|
||||
// nil если очереди нет. Вызывающий ОБЯЗАН вызвать q.UnlockMu().
|
||||
func (s *QueueStore) GetLocked(key string) *Queue {
|
||||
s.RLock()
|
||||
q := s.Queues[key]
|
||||
s.RUnlock()
|
||||
if q == nil {
|
||||
return nil
|
||||
}
|
||||
q.LockMu()
|
||||
return q
|
||||
}
|
||||
|
||||
// GetRLocked — то же, но read-блокировка. Вызывающий ОБЯЗАН вызвать q.RUnlockMu().
|
||||
func (s *QueueStore) GetRLocked(key string) *Queue {
|
||||
s.RLock()
|
||||
q := s.Queues[key]
|
||||
s.RUnlock()
|
||||
if q == nil {
|
||||
return nil
|
||||
}
|
||||
q.RLockMu()
|
||||
return q
|
||||
}
|
||||
|
||||
// CountTenantQueues — число очередей тенанта (по accessKey) за O(1).
|
||||
// Вызывать под SyncQueues.RLock() или Lock().
|
||||
func (s *QueueStore) CountTenantQueues(accessKey string) int {
|
||||
|
||||
Reference in New Issue
Block a user