feat(cooler): Cache.Pull returns and removes a value atomically
- Cache.Pull(ctx, key) ([]byte, bool, error), Laravel's Cache::pull
- Redis driver runs GETDEL (Redis 6.2+); memory driver uses otter Compute
with InvalidateOp under the per-key lock; expired keys report not found
- TestPullSmoke over the memory driver and miniredis, ExampleCache_Pull
- README and docs/services/caching.md ("One-time values")
This commit is contained in:
@@ -84,6 +84,27 @@ func (m *memoryCache) Get(_ context.Context, key string) ([]byte, bool, error) {
|
||||
return clone(e.val), true, nil
|
||||
}
|
||||
|
||||
// Pull returns the value at key and removes it under otter's per-key lock, so
|
||||
// of two concurrent callers at most one sees found=true. An expired entry is
|
||||
// removed too and reported as not found.
|
||||
func (m *memoryCache) Pull(_ context.Context, key string) ([]byte, bool, error) {
|
||||
var (
|
||||
out []byte
|
||||
found bool
|
||||
)
|
||||
now := time.Now()
|
||||
m.c.Compute(m.key(key), func(old memEntry, ok bool) (memEntry, otter.ComputeOp) {
|
||||
if !ok {
|
||||
return old, otter.CancelOp
|
||||
}
|
||||
if !old.expired(now) {
|
||||
out, found = clone(old.val), true
|
||||
}
|
||||
return memEntry{}, otter.InvalidateOp
|
||||
})
|
||||
return out, found, nil
|
||||
}
|
||||
|
||||
func (m *memoryCache) Set(_ context.Context, key string, value []byte, ttl time.Duration) error {
|
||||
e := memEntry{val: clone(value)}
|
||||
if ttl > 0 {
|
||||
|
||||
Reference in New Issue
Block a user