113 lines
4.0 KiB
Go
113 lines
4.0 KiB
Go
package redisstate
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"galaxy/mail/internal/domain/attempt"
|
|
deliverydomain "galaxy/mail/internal/domain/delivery"
|
|
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/redis/go-redis/v9"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestIndexCleanerRemovesStaleMembersAfterDeliveryExpiry(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
server := miniredis.RunT(t)
|
|
client := redis.NewClient(&redis.Options{Addr: server.Addr()})
|
|
t.Cleanup(func() { require.NoError(t, client.Close()) })
|
|
|
|
writer, err := NewAtomicWriter(client)
|
|
require.NoError(t, err)
|
|
cleaner, err := NewIndexCleaner(client)
|
|
require.NoError(t, err)
|
|
|
|
record := validDelivery(t)
|
|
record.Source = deliverydomain.SourceNotification
|
|
record.ResendParentDeliveryID = ""
|
|
record.Status = deliverydomain.StatusQueued
|
|
record.SentAt = nil
|
|
record.LocaleFallbackUsed = false
|
|
record.UpdatedAt = record.CreatedAt.Add(time.Minute)
|
|
require.NoError(t, record.Validate())
|
|
|
|
input := CreateAcceptanceInput{
|
|
Delivery: record,
|
|
FirstAttempt: ptr(validScheduledAttempt(t, record.DeliveryID)),
|
|
Idempotency: ptr(validIdempotencyRecord(t, record.Source, record.DeliveryID, record.IdempotencyKey)),
|
|
}
|
|
require.NoError(t, writer.CreateAcceptance(context.Background(), input))
|
|
|
|
deadLetterEntry := validDeadLetterEntry(t, record.DeliveryID)
|
|
deadLetterPayload, err := MarshalDeadLetter(deadLetterEntry)
|
|
require.NoError(t, err)
|
|
require.NoError(t, client.Set(context.Background(), Keyspace{}.DeadLetter(record.DeliveryID), deadLetterPayload, DeadLetterTTL).Err())
|
|
|
|
server.FastForward(DeliveryTTL + time.Second)
|
|
|
|
require.False(t, server.Exists(Keyspace{}.Delivery(record.DeliveryID)))
|
|
require.True(t, server.Exists(Keyspace{}.Attempt(record.DeliveryID, input.FirstAttempt.AttemptNo)))
|
|
require.True(t, server.Exists(Keyspace{}.DeadLetter(record.DeliveryID)))
|
|
|
|
report, err := cleaner.CleanDeliveryIndexes(context.Background())
|
|
require.NoError(t, err)
|
|
require.Positive(t, report.ScannedIndexes)
|
|
require.Positive(t, report.ScannedMembers)
|
|
require.Positive(t, report.RemovedMembers)
|
|
|
|
assertZCard := func(key string, want int64) {
|
|
t.Helper()
|
|
|
|
got, err := client.ZCard(context.Background(), key).Result()
|
|
require.NoError(t, err)
|
|
require.Equal(t, want, got)
|
|
}
|
|
|
|
assertZCard(Keyspace{}.CreatedAtIndex(), 0)
|
|
assertZCard(Keyspace{}.SourceIndex(record.Source), 0)
|
|
assertZCard(Keyspace{}.StatusIndex(record.Status), 0)
|
|
assertZCard(Keyspace{}.RecipientIndex(record.Envelope.To[0]), 0)
|
|
assertZCard(Keyspace{}.RecipientIndex(record.Envelope.Cc[0]), 0)
|
|
assertZCard(Keyspace{}.RecipientIndex(record.Envelope.Bcc[0]), 0)
|
|
assertZCard(Keyspace{}.TemplateIndex(record.TemplateID), 0)
|
|
assertZCard(Keyspace{}.IdempotencyIndex(record.Source, record.IdempotencyKey), 0)
|
|
|
|
require.True(t, server.Exists(Keyspace{}.Attempt(record.DeliveryID, input.FirstAttempt.AttemptNo)))
|
|
require.True(t, server.Exists(Keyspace{}.DeadLetter(record.DeliveryID)))
|
|
scheduleCard, err := client.ZCard(context.Background(), Keyspace{}.AttemptSchedule()).Result()
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, 1, scheduleCard)
|
|
}
|
|
|
|
func TestIndexCleanerSkipsMalformedCommandIndex(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
server := miniredis.RunT(t)
|
|
client := redis.NewClient(&redis.Options{Addr: server.Addr()})
|
|
t.Cleanup(func() { require.NoError(t, client.Close()) })
|
|
|
|
cleaner, err := NewIndexCleaner(client)
|
|
require.NoError(t, err)
|
|
|
|
entry := validMalformedCommandEntry(t)
|
|
require.NoError(t, client.ZAdd(context.Background(), Keyspace{}.MalformedCommandCreatedAtIndex(), redis.Z{
|
|
Score: float64(entry.RecordedAt.UTC().UnixMilli()),
|
|
Member: entry.StreamEntryID,
|
|
}).Err())
|
|
|
|
report, err := cleaner.CleanDeliveryIndexes(context.Background())
|
|
require.NoError(t, err)
|
|
require.Zero(t, report.ScannedIndexes)
|
|
require.Zero(t, report.ScannedMembers)
|
|
require.Zero(t, report.RemovedMembers)
|
|
|
|
indexMembers, err := client.ZRange(context.Background(), Keyspace{}.MalformedCommandCreatedAtIndex(), 0, -1).Result()
|
|
require.NoError(t, err)
|
|
require.Equal(t, []string{entry.StreamEntryID}, indexMembers)
|
|
}
|
|
|
|
var _ = attempt.Attempt{}
|