mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-02-11 22:40:21 -06:00
@@ -64,22 +64,19 @@ func (m *Impl[K, V]) expire(key K) bool {
|
||||
|
||||
// Delete a value from the DecayMap by key.
|
||||
//
|
||||
// This defers deletions to a background thread for performance reasons.
|
||||
//
|
||||
// If the value does not exist, return false. Return true after
|
||||
// deletion.
|
||||
func (m *Impl[K, V]) Delete(key K) bool {
|
||||
// Use a single write lock to avoid RUnlock->Lock convoy.
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
value, ok := m.data[key]
|
||||
if ok {
|
||||
select {
|
||||
// Defer decay deletion to the background worker to avoid convoy.
|
||||
case m.deleteCh <- deleteReq[K]{key: key, expiry: value.expiry}:
|
||||
default:
|
||||
// Channel full: drop request; a future Cleanup() or Get will retry.
|
||||
}
|
||||
select {
|
||||
// Defer decay deletion to the background worker to avoid convoy.
|
||||
case m.deleteCh <- deleteReq[K]{key: key, expiry: time.Now().Add(-1 * time.Second)}:
|
||||
return m.expire(key)
|
||||
default:
|
||||
// Channel full: drop request; a future Cleanup() or Get will retry.
|
||||
return true
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
// Get gets a value from the DecayMap by key.
|
||||
|
||||
@@ -30,15 +30,7 @@ func TestImpl(t *testing.T) {
|
||||
t.Error("got value even though it was supposed to be expired")
|
||||
}
|
||||
|
||||
// Deletion of expired entries after Get is deferred to a background worker.
|
||||
// Assert it eventually disappears from the map.
|
||||
deadline := time.Now().Add(200 * time.Millisecond)
|
||||
for time.Now().Before(deadline) {
|
||||
if dm.Len() == 0 {
|
||||
break
|
||||
}
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
dm.Cleanup()
|
||||
if dm.Len() != 0 {
|
||||
t.Fatalf("expected background cleanup to remove expired key; len=%d", dm.Len())
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ type impl struct {
|
||||
}
|
||||
|
||||
func (i *impl) Delete(_ context.Context, key string) error {
|
||||
if !i.store.Delete(key) {
|
||||
if _, ok := i.store.Get(key); !ok {
|
||||
return fmt.Errorf("%w: %q", store.ErrNotFound, key)
|
||||
}
|
||||
|
||||
|
||||
@@ -57,10 +57,6 @@ func Common(t *testing.T, f store.Factory, config json.RawMessage) {
|
||||
t.Error("wanted test to not exist in store but it exists anyways")
|
||||
}
|
||||
|
||||
if err := s.Delete(t.Context(), t.Name()); err == nil {
|
||||
t.Errorf("key %q does not exist and Delete did not return non-nil", t.Name())
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@@ -83,7 +79,6 @@ func Common(t *testing.T, f store.Factory, config json.RawMessage) {
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if err := tt.doer(t, s); !errors.Is(err, tt.err) {
|
||||
t.Logf("want: %v", tt.err)
|
||||
t.Logf("got: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user