End an unassigned key with ended and remove no key of the chain (issue 1093)

ADR 0408 section 4 says no key of the chain is removed, a delete marker included. The Backend loses Remove and the Chain RemoveAssignment. An unassignment, and the end of a value only pulled in by another, write the value again with ended set, by compare-and-set; assigning it again writes a fresh standing value over it. A value with ended or a state is no assignment (Assignment.Stands) to the assignment lists, the joins, forgetting a module, seat holdings, the given values, the move and the assignment-changed event.
This commit is contained in:
2026-10-18 03:17:47 +02:00
parent 0e4feb0d3a
commit cb00bbbfcf
7 changed files with 125 additions and 122 deletions
+3 -29
View File
@@ -35,10 +35,6 @@ type Backend interface {
Watch(ctx context.Context) (<-chan Entry, error)
// History is a key's earlier values and its current one, oldest first, at most the bucket keeps.
History(ctx context.Context, key string) ([]Entry, error)
// Remove ends a key at the revision it was read at, with a marker: **its earlier values stay**, read back by History, and
// nothing is purged. Used by an unassignment and by nothing else, in the delivery that moves the assignments; the
// delivery after it keeps an unassigned key with an end mark and removes this (issue 1096).
Remove(ctx context.Context, key string, revision uint64) error
}
var (
@@ -101,10 +97,10 @@ func (m *Memory) now() time.Time {
return time.Now()
}
// last is a key's newest entry, false when it holds none or was removed.
// last is a key's newest entry, false when it holds none.
func (m *Memory) last(key string) (Entry, bool) {
h := m.values[key]
if len(h) == 0 || h[len(h)-1].Deleted {
if len(h) == 0 {
return Entry{}, false
}
return h[len(h)-1], true
@@ -123,26 +119,6 @@ func (m *Memory) Get(_ context.Context, key string) (Entry, bool, error) {
return clone(e), true, nil
}
func (m *Memory) Remove(_ context.Context, key string, revision uint64) error {
m.mu.Lock()
defer m.mu.Unlock()
if m.fail != nil {
return m.fail
}
e, ok := m.last(key)
if !ok || e.Revision != revision {
return ErrMoved
}
m.revision++
m.writes++
h := append(m.values[key], Entry{Key: key, Deleted: true, Revision: m.revision, At: m.now()})
if len(h) > m.keep() {
h = h[len(h)-m.keep():]
}
m.values[key] = h
return nil
}
func (m *Memory) Create(_ context.Context, key string, value []byte) (uint64, error) {
m.mu.Lock()
defer m.mu.Unlock()
@@ -288,9 +264,7 @@ func (m *Memory) History(_ context.Context, key string) ([]Entry, error) {
}
out := make([]Entry, 0, len(m.values[key]))
for _, e := range m.values[key] {
if !e.Deleted {
out = append(out, clone(e))
}
out = append(out, clone(e))
}
return out, nil
}