P1.2: индексация сообщений — tombstone-удаление O(1), receipt/uuid-индексы, tick по in-flight
- models.Queue: deadIdx/receiptIdx/uuidIdx/liveCount/deadCount + примитивы (AppendMessage/RemoveIndex/Compact/CompactIfNeeded/Reset/EnsureIndexes/ IndexOfReceipt/IndexOfUUID/MarkInFlight/ClearInFlight/InFlightIndexes/LiveCount). Удаление — tombstone за O(1), физическая чистка амортизированная. - DeleteMessage/ChangeMessageVisibility(±Batch): поиск по индексу вместо скана среза; удаление без сдвига остатка. - DeleteMessageBatch: tombstone вместо полной пересборки среза. - processQueueTick: visibility/DLQ по индексу in-flight (O(in-flight)), retention — tombstone, в конце — CompactIfNeeded. - send-пути: AppendMessage + LiveCount (OOM-лимит по живым). - admin/metrics/persistence: учёт живых сообщений, индексы после загрузки из Redis. - Redis-схема не менялась (сообщения и так в per-message HASH).
This commit is contained in:
+16
-9
@@ -461,8 +461,11 @@ func (h *Handler) listTenantQueues(w http.ResponseWriter, r *http.Request) {
|
||||
p.q.RLockMu()
|
||||
visible := 0
|
||||
notVisible := 0
|
||||
for _, msg := range p.q.Messages {
|
||||
if msg.ReceiptHandle != "" {
|
||||
for i := range p.q.Messages {
|
||||
if p.q.IsDead(i) {
|
||||
continue
|
||||
}
|
||||
if p.q.Messages[i].ReceiptHandle != "" {
|
||||
notVisible++
|
||||
} else {
|
||||
visible++
|
||||
@@ -598,11 +601,15 @@ func (h *Handler) peekQueueMessages(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
q.RLockMu()
|
||||
result := make([]peekMessageItem, 0, len(q.Messages))
|
||||
for i, msg := range q.Messages {
|
||||
if i >= limit {
|
||||
result := make([]peekMessageItem, 0, limit)
|
||||
for i := range q.Messages {
|
||||
if len(result) >= limit {
|
||||
break
|
||||
}
|
||||
if q.IsDead(i) {
|
||||
continue
|
||||
}
|
||||
msg := &q.Messages[i]
|
||||
result = append(result, peekMessageItem{
|
||||
ID: msg.Uuid,
|
||||
Body: msg.MessageBody,
|
||||
@@ -652,7 +659,7 @@ func (h *Handler) sendMessageToQueue(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
msg := gosqs.BuildSqsMessage(req.Body)
|
||||
q.Messages = append(q.Messages, msg)
|
||||
q.AppendMessage(msg)
|
||||
// Персистим одно сообщение отдельно
|
||||
persistence.SaveMessage(key, &msg)
|
||||
persistence.SaveQueue(key, q)
|
||||
@@ -678,7 +685,7 @@ func (h *Handler) purgeQueue(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
q.LockMu()
|
||||
q.Messages = q.Messages[:0]
|
||||
q.Reset()
|
||||
// Удаляем все сообщения из Redis одной командой
|
||||
persistence.PurgeMessagesPersist(key)
|
||||
persistence.SaveQueue(key, q)
|
||||
@@ -720,7 +727,7 @@ func (h *Handler) detailedHealth(w http.ResponseWriter, r *http.Request) {
|
||||
models.SyncQueues.RUnlock()
|
||||
for _, q := range uiQueues {
|
||||
q.RLockMu()
|
||||
msgCount += len(q.Messages)
|
||||
msgCount += q.LiveCount()
|
||||
q.RUnlockMu()
|
||||
}
|
||||
|
||||
@@ -745,7 +752,7 @@ func (h *Handler) detailedHealth(w http.ResponseWriter, r *http.Request) {
|
||||
msgCount := 0
|
||||
for _, q := range allQueues {
|
||||
q.RLockMu()
|
||||
msgCount += len(q.Messages)
|
||||
msgCount += q.LiveCount()
|
||||
q.RUnlockMu()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user