// Изменено: 2026-04-09 // Helper-функции для tenant-scoped операций с очередями. // Используются всеми SQS handlers для изоляции очередей между тенантами. package gosqs import ( "net/http" "strings" "shared-sqs/app/auth" "shared-sqs/app/models" "shared-sqs/app/tenant" ) // tenantQueueKey — внутренний ключ очереди в SyncQueues в формате "{accessKey}:{queueName}". // Такой формат гарантирует изоляцию: тенант видит только очереди с префиксом своего accessKey. func tenantQueueKey(tenantAccessKey, queueName string) string { return tenantAccessKey + ":" + queueName } // dlqKeyFor — ключ DLQ по ключу исходной очереди (формат "{accessKey}:{name}") // и имени DLQ. Используется для персиста перенесённых в DLQ сообщений. func dlqKeyFor(srcKey, dlqName string) string { idx := strings.LastIndex(srcKey, ":") if idx < 0 { return srcKey + ":" + dlqName } return srcKey[:idx] + ":" + dlqName } func getTenantFromContext(r *http.Request) *tenant.Tenant { t, _ := r.Context().Value(auth.TenantContextKey).(*tenant.Tenant) return t } // tenantQueueURL — формирует URL очереди для тенанта. // Ловушка #10: QueueUrl ОБЯЗАН содержать tenantID в пути, иначе AWS SDK не сможет send/receive. func tenantQueueURL(t *tenant.Tenant, queueName string) string { // Публичный адрес (напр. https://sqs.sinefo.ru) — приоритетнее локального формата. if base := strings.TrimRight(models.CurrentEnvironment.ExternalURLBase, "/"); base != "" { return base + "/" + t.ID + "/" + queueName } host := models.CurrentEnvironment.Host port := models.CurrentEnvironment.Port region := models.CurrentEnvironment.Region if region != "" { return "http://" + region + "." + host + ":" + port + "/" + t.ID + "/" + queueName } return "http://" + host + ":" + port + "/" + t.ID + "/" + queueName } // TenantQueueURL — экспортированная обёртка над tenantQueueURL (нужна app/cmd). func TenantQueueURL(t *tenant.Tenant, queueName string) string { return tenantQueueURL(t, queueName) } // tenantQueueARN — формирует ARN очереди для тенанта. func tenantQueueARN(t *tenant.Tenant, queueName string) string { return "arn:aws:sqs:" + models.CurrentEnvironment.Region + ":" + t.ID + ":" + queueName } // countTenantQueues — считает количество очередей тенанта (через tenant-индекс, O(1)). // Используется для проверки лимита MaxQueues. // Вызывать под SyncQueues.RLock()/Lock(). func countTenantQueues(tenantAccessKey string) int { return models.SyncQueues.CountTenantQueues(tenantAccessKey) }