Files
QSfera/Server/vendor/github.com/nats-io/nats-server/v2/server/sdm.go
T
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

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
}
}
}
}