81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
// Copyright 2025 The NATS Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package server
|
|
|
|
import (
|
|
"bytes"
|
|
"time"
|
|
)
|
|
|
|
// SDMMeta holds pending/proposed data for subject delete markers or message removals.
|
|
type SDMMeta struct {
|
|
totals map[string]uint64
|
|
pending map[uint64]SDMBySeq
|
|
}
|
|
|
|
// SDMBySeq holds data for a message with a specific sequence.
|
|
type SDMBySeq struct {
|
|
last bool // Whether the message for this sequence was the last for this subject.
|
|
ts int64 // Last timestamp we proposed a removal/sdm.
|
|
}
|
|
|
|
func newSDMMeta() *SDMMeta {
|
|
return &SDMMeta{
|
|
totals: make(map[string]uint64, 1),
|
|
pending: make(map[uint64]SDMBySeq, 1),
|
|
}
|
|
}
|
|
|
|
// isSubjectDeleteMarker returns whether the headers indicate this message is a subject delete marker.
|
|
// Either it's a usual marker with JSMarkerReason, or it's a KV Purge marker as the KVOperation.
|
|
func isSubjectDeleteMarker(hdr []byte) bool {
|
|
return len(sliceHeader(JSMarkerReason, hdr)) != 0 || bytes.Equal(sliceHeader(KVOperation, hdr), KVOperationValuePurge)
|
|
}
|
|
|
|
// empty clears all data.
|
|
func (sdm *SDMMeta) empty() {
|
|
if sdm == nil {
|
|
return
|
|
}
|
|
clear(sdm.totals)
|
|
clear(sdm.pending)
|
|
}
|
|
|
|
// trackPending caches the given seq and subj and whether it's the last message for that subject.
|
|
func (sdm *SDMMeta) trackPending(seq uint64, subj string, last bool) bool {
|
|
if p, ok := sdm.pending[seq]; ok {
|
|
return p.last
|
|
}
|
|
sdm.pending[seq] = SDMBySeq{last, time.Now().UnixNano()}
|
|
sdm.totals[subj]++
|
|
return last
|
|
}
|
|
|
|
// removeSeqAndSubject clears the seq and subj from the cache.
|
|
func (sdm *SDMMeta) removeSeqAndSubject(seq uint64, subj string) {
|
|
if sdm == nil {
|
|
return
|
|
}
|
|
if _, ok := sdm.pending[seq]; ok {
|
|
delete(sdm.pending, seq)
|
|
if msgs, ok := sdm.totals[subj]; ok {
|
|
if msgs <= 1 {
|
|
delete(sdm.totals, subj)
|
|
} else {
|
|
sdm.totals[subj] = msgs - 1
|
|
}
|
|
}
|
|
}
|
|
}
|