fix: snapshot queued log entries

This commit is contained in:
MiMoCode
2026-07-10 19:20:09 +08:00
parent 01df0e8eb4
commit 6773d088c3
2 changed files with 56 additions and 2 deletions
+12 -2
View File
@@ -235,7 +235,8 @@ func (q *Queue) Submit(e *LogEntry) {
q.dropped.Add(1) q.dropped.Add(1)
return return
} }
size := EstimatedBytes(e) entry := cloneLogEntry(e)
size := EstimatedBytes(entry)
if !q.mu.TryRLock() { if !q.mu.TryRLock() {
q.dropped.Add(1) q.dropped.Add(1)
return return
@@ -246,7 +247,7 @@ func (q *Queue) Submit(e *LogEntry) {
return return
} }
select { select {
case q.ch <- queuedEntry{entry: e, size: size}: case q.ch <- queuedEntry{entry: entry, size: size}:
q.enq.Add(1) q.enq.Add(1)
default: default:
q.release(size) q.release(size)
@@ -255,6 +256,15 @@ func (q *Queue) Submit(e *LogEntry) {
q.mu.RUnlock() q.mu.RUnlock()
} }
func cloneLogEntry(entry *LogEntry) *LogEntry {
clone := *entry
clone.RequestHeaders = append([]byte(nil), entry.RequestHeaders...)
clone.RequestBody = append([]byte(nil), entry.RequestBody...)
clone.ResponseHeaders = append([]byte(nil), entry.ResponseHeaders...)
clone.ResponseBody = append([]byte(nil), entry.ResponseBody...)
return &clone
}
func (q *Queue) reserve(size int64) bool { func (q *Queue) reserve(size int64) bool {
for { for {
used := q.entries.Load() used := q.entries.Load()
+44
View File
@@ -314,6 +314,50 @@ func TestQueueReleasesSubmittedSizeAfterEntryMutation(t *testing.T) {
} }
} }
func TestQueueSubmitOwnsEntrySnapshot(t *testing.T) {
prepareStarted := make(chan struct{})
releasePrepare := make(chan struct{})
batch := &fakeBatch{}
backend := newQueueBackend(func(context.Context, string) (logger.Batch, error) {
close(prepareStarted)
<-releasePrepare
return batch, nil
})
entry := &logger.LogEntry{
RequestID: "original-id",
RequestHeaders: []byte("original-request-headers"),
RequestBody: []byte("original-request-body"),
ResponseHeaders: []byte("original-response-headers"),
ResponseBody: []byte("original-response-body"),
}
q := logger.NewQueueWithBackend(backend, 1, 1, 1, time.Hour)
q.Start(context.Background())
q.Submit(entry)
<-prepareStarted
entry.RequestID = "mutated-id"
entry.RequestHeaders[0] = 'X'
entry.RequestBody[0] = 'X'
entry.ResponseHeaders[0] = 'X'
entry.ResponseBody[0] = 'X'
close(releasePrepare)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := q.Stop(ctx); err != nil {
t.Fatalf("Stop: %v", err)
}
if len(batch.rows) != 1 {
t.Fatalf("written rows=%d want 1", len(batch.rows))
}
row := batch.rows[0]
if row[0] != "original-id" ||
row[5] != "original-request-headers" || row[6] != "original-request-body" ||
row[9] != "original-response-headers" || row[10] != "original-response-body" {
t.Fatalf("queued entry changed after Submit: %#v", row)
}
}
func TestQueueCanceledStopEventuallyReleasesAllBudget(t *testing.T) { func TestQueueCanceledStopEventuallyReleasesAllBudget(t *testing.T) {
entry := &logger.LogEntry{RequestID: "queued"} entry := &logger.LogEntry{RequestID: "queued"}
q := logger.NewQueue(nil, 32, 32, 1, time.Hour, 32*logger.EstimatedBytes(entry)) q := logger.NewQueue(nil, 32, 32, 1, time.Hour, 32*logger.EstimatedBytes(entry))