P1.4: tenant-индекс очередей (O(1) подсчёт/список вместо скана)
Введён тип QueueStore с индексом accessKey→{queueName}. Мутации очередей идут через
AddQueue/RemoveQueue (create/delete/restore/config/seed/admin), подсчёт и список —
через CountTenantQueues/TenantQueueNames. Устранены O(total) скан-по-префиксу в
countTenantQueues, deleteTenant, listTenantQueues, createTenantQueue. API SyncQueues
(Queues, Lock) сохранён — остальной код не затронут.
This commit is contained in:
+34
-38
@@ -405,15 +405,14 @@ func (h *Handler) deleteTenant(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "tenant not found"})
|
||||
return
|
||||
}
|
||||
// Удаляем все очереди тенанта из SyncQueues
|
||||
prefix := t.AccessKey + ":"
|
||||
deletedQueueKeys := make([]string, 0)
|
||||
// Удаляем все очереди тенанта из SyncQueues (через tenant-индекс, без скана всех очередей)
|
||||
models.SyncQueues.Lock()
|
||||
for key := range models.SyncQueues.Queues {
|
||||
if strings.HasPrefix(key, prefix) {
|
||||
deletedQueueKeys = append(deletedQueueKeys, key)
|
||||
delete(models.SyncQueues.Queues, key)
|
||||
}
|
||||
tenantQueueNames := models.SyncQueues.TenantQueueNames(t.AccessKey)
|
||||
deletedQueueKeys := make([]string, 0, len(tenantQueueNames))
|
||||
for _, name := range tenantQueueNames {
|
||||
key := t.AccessKey + ":" + name
|
||||
deletedQueueKeys = append(deletedQueueKeys, key)
|
||||
models.SyncQueues.RemoveQueue(key)
|
||||
}
|
||||
models.SyncQueues.Unlock()
|
||||
for _, queueKey := range deletedQueueKeys {
|
||||
@@ -447,27 +446,28 @@ func (h *Handler) listTenantQueues(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
queues := make([]queueInfo, 0)
|
||||
models.SyncQueues.RLock()
|
||||
for key, q := range models.SyncQueues.Queues {
|
||||
if strings.HasPrefix(key, prefix) {
|
||||
name := strings.TrimPrefix(key, prefix)
|
||||
visible := 0
|
||||
notVisible := 0
|
||||
for _, msg := range q.Messages {
|
||||
if msg.ReceiptHandle != "" {
|
||||
notVisible++
|
||||
} else {
|
||||
visible++
|
||||
}
|
||||
}
|
||||
queues = append(queues, queueInfo{
|
||||
Name: name,
|
||||
Messages: visible,
|
||||
NotVisible: notVisible,
|
||||
VisibilityTimeout: q.VisibilityTimeout,
|
||||
MaxMessageSize: q.MaximumMessageSize,
|
||||
RetentionPeriod: q.MessageRetentionPeriod,
|
||||
})
|
||||
for _, name := range models.SyncQueues.TenantQueueNames(t.AccessKey) {
|
||||
q := models.SyncQueues.Queues[prefix+name]
|
||||
if q == nil {
|
||||
continue
|
||||
}
|
||||
visible := 0
|
||||
notVisible := 0
|
||||
for _, msg := range q.Messages {
|
||||
if msg.ReceiptHandle != "" {
|
||||
notVisible++
|
||||
} else {
|
||||
visible++
|
||||
}
|
||||
}
|
||||
queues = append(queues, queueInfo{
|
||||
Name: name,
|
||||
Messages: visible,
|
||||
NotVisible: notVisible,
|
||||
VisibilityTimeout: q.VisibilityTimeout,
|
||||
MaxMessageSize: q.MaximumMessageSize,
|
||||
RetentionPeriod: q.MessageRetentionPeriod,
|
||||
})
|
||||
}
|
||||
models.SyncQueues.RUnlock()
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -504,19 +504,14 @@ func (h *Handler) createTenantQueue(w http.ResponseWriter, r *http.Request) {
|
||||
jsonErr(w, http.StatusConflict, "queue already exists")
|
||||
return
|
||||
}
|
||||
// Проверяем лимит очередей тенанта
|
||||
count := 0
|
||||
for k := range models.SyncQueues.Queues {
|
||||
if strings.HasPrefix(k, t.AccessKey+":") {
|
||||
count++
|
||||
}
|
||||
}
|
||||
// Проверяем лимит очередей тенанта (через tenant-индекс, O(1))
|
||||
count := models.SyncQueues.CountTenantQueues(t.AccessKey)
|
||||
if t.MaxQueues > 0 && count >= t.MaxQueues {
|
||||
models.SyncQueues.Unlock()
|
||||
jsonErr(w, http.StatusForbidden, "queue limit exceeded")
|
||||
return
|
||||
}
|
||||
models.SyncQueues.Queues[key] = &models.Queue{
|
||||
newQueue := &models.Queue{
|
||||
Name: req.Name,
|
||||
VisibilityTimeout: 30,
|
||||
MaximumMessageSize: 262144,
|
||||
@@ -524,7 +519,8 @@ func (h *Handler) createTenantQueue(w http.ResponseWriter, r *http.Request) {
|
||||
Messages: []models.SqsMessage{},
|
||||
Duplicates: make(map[string]time.Time),
|
||||
}
|
||||
persistence.SaveQueue(key, models.SyncQueues.Queues[key])
|
||||
models.SyncQueues.AddQueue(key, newQueue)
|
||||
persistence.SaveQueue(key, newQueue)
|
||||
models.SyncQueues.Unlock()
|
||||
log.Infof("admin: created queue %s for tenant %s", req.Name, t.ID)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -549,7 +545,7 @@ func (h *Handler) deleteTenantQueue(w http.ResponseWriter, r *http.Request) {
|
||||
jsonErr(w, http.StatusNotFound, "queue not found")
|
||||
return
|
||||
}
|
||||
delete(models.SyncQueues.Queues, key)
|
||||
models.SyncQueues.RemoveQueue(key)
|
||||
models.SyncQueues.Unlock()
|
||||
persistence.DeleteQueue(key)
|
||||
log.Infof("admin: deleted queue %s for tenant %s", queueName, t.ID)
|
||||
|
||||
Reference in New Issue
Block a user