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>
104 lines
2.2 KiB
Go
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)
|
|
}
|