Files
weichenandCursor 2d0fcb94bc fix(docrevision): keep PG snapshot IDs ahead of in-memory counters
Opening a template stored database IDs without advancing nextSnapID, so the next temporary snapshot could overwrite and then delete the real baseline. Adopt helpers now bump every counter and only drop a map entry when it still points at the same object.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 23:43:56 +00:00

104 lines
2.2 KiB
Go

package docrevision
// advanceID 把进程内分配计数推进到不少于已落库 ID,避免下一临时 ID 撞上真实对象。
func advanceID(counter *int64, id int64) {
if counter == nil || id <= 0 {
return
}
if id > *counter {
*counter = id
}
}
// nextFreeID 分配一个当前 map 中未被占用的临时 ID。
func nextFreeID(counter *int64, occupied func(int64) bool) int64 {
if counter == nil {
return 0
}
for {
*counter++
id := *counter
if occupied == nil || !occupied(id) {
return id
}
}
}
func (s *Service) adoptSnapshotID(snap *Snapshot, dbID int64) {
if s == nil || snap == nil || dbID <= 0 {
return
}
oldID := snap.ID
if oldID != 0 && oldID != dbID {
if existing := s.snapshots[oldID]; existing == snap {
delete(s.snapshots, oldID)
}
}
snap.ID = dbID
s.snapshots[dbID] = snap
advanceID(&s.nextSnapID, dbID)
}
func (s *Service) adoptVersionID(ver *Version, dbID int64) {
if s == nil || ver == nil || dbID <= 0 {
return
}
oldID := ver.ID
if oldID != 0 && oldID != dbID {
if existing := s.versions[oldID]; existing == ver {
delete(s.versions, oldID)
}
}
ver.ID = dbID
s.versions[dbID] = ver
advanceID(&s.nextVerID, dbID)
}
func (s *Service) adoptEventID(ev *ChangeEvent, dbID int64) {
if s == nil || ev == nil || dbID <= 0 {
return
}
oldID := ev.ID
if oldID != 0 && oldID != dbID {
if existing := s.events[oldID]; existing == ev {
delete(s.events, oldID)
}
}
ev.ID = dbID
s.events[dbID] = ev
if ev.IdempotencyKey != "" {
s.idemp[ev.IdempotencyKey] = dbID
}
advanceID(&s.nextEvtID, dbID)
}
func (s *Service) adoptReportID(rep *ChangeReport, dbID int64) {
if s == nil || rep == nil || dbID <= 0 {
return
}
oldID := rep.ID
if oldID != 0 && oldID != dbID {
if existing := s.reports[oldID]; existing == rep {
delete(s.reports, oldID)
}
}
rep.ID = dbID
s.reports[dbID] = rep
advanceID(&s.nextRepID, dbID)
}
func (s *Service) adoptCandidateID(c *AgentCandidate, dbID int64) {
if s == nil || c == nil || dbID <= 0 {
return
}
oldID := c.ID
if oldID != 0 && oldID != dbID {
if existing := s.candidates[oldID]; existing == c {
delete(s.candidates, oldID)
}
}
c.ID = dbID
s.candidates[dbID] = c
advanceID(&s.nextCandID, dbID)
}