Documentation
¶
Overview ¶
Package memorycache provides an in-memory cache.Driver for tests, local development, and single-process applications.
Every context-aware operation returns ctx.Err() before reading or mutating state. Put and successful Add copy supplied byte slices, and Get returns a copy, so caller mutation cannot change cached state. A zero TTL does not expire. CompareAndPut compares an existing guard and writes its destination under one mutex, including when the keys differ. Its successful write copies the supplied bytes; a mismatch preserves the entries and their lifetimes. Counter lookup, checked arithmetic, and write also share one mutex. Results outside int64 wrap strconv.ErrRange without changing the target value or TTL or creating a missing entry. Decrement checks subtraction directly, so a MinInt64 delta works whenever the mathematical result is representable.
New takes Builder policies for Cleanup. They run directly once in order on a fresh draft; nil entries panic and expanded nil/empty slices supply no edits. Zero cleanup resolves to one minute; negative disables sweeping. Publication detaches settings and retained drafts cannot change the driver's lifecycle. Construction starts no janitor; Start owns any background work.
Example:
driver := memorycache.New(func(store *memorycache.Builder) {
store.Cleanup(-time.Second)
})
store := cache.New(driver)
_ = store.Driver()
Index ¶
- type Builder
- type BuilderFunc
- type Driver
- func (driver *Driver) Add(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error)
- func (driver *Driver) CompareAndPut(ctx context.Context, match cache.Match, entry cache.Entry) (bool, error)
- func (driver *Driver) Decrement(ctx context.Context, key string, delta int64) (int64, error)
- func (driver *Driver) Delete(ctx context.Context, key string) error
- func (driver *Driver) ExtendLock(ctx context.Context, name, token string, ttl time.Duration) (bool, error)
- func (driver *Driver) Get(ctx context.Context, key string) ([]byte, error)
- func (driver *Driver) Has(ctx context.Context, key string) (bool, error)
- func (driver *Driver) Increment(ctx context.Context, key string, delta int64) (int64, error)
- func (driver *Driver) IncrementWithTTL(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, time.Duration, error)
- func (driver *Driver) Pull(ctx context.Context, key string) ([]byte, error)
- func (driver *Driver) Put(ctx context.Context, key string, value []byte, ttl time.Duration) error
- func (driver *Driver) Start(ctx context.Context) error
- func (driver *Driver) Stop(ctx context.Context) error
- func (driver *Driver) TTL(ctx context.Context, key string) (time.Duration, error)
- func (driver *Driver) TryLock(ctx context.Context, name, token string, ttl time.Duration) (bool, error)
- func (driver *Driver) Unlock(ctx context.Context, name, token string) (bool, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder configures New before publication. Callbacks run directly once, synchronously in order on one fresh draft. Nil callback entries panic; expanded nil or empty callback slices supply no edits. Retaining the draft cannot change published settings. Methods return the same draft.
Example:
memorycache.New(func(store *memorycache.Builder) {
store.Cleanup(-time.Second)
})
func (*Builder) Cleanup ¶
Cleanup sets the minimum interval between inline expiry sweeps and, when started, janitor sweeps. Zero resolves to one minute; negative disables both kinds of sweeping. Expired entries are still removed when accessed.
This setting replaces the previous value on the construction draft. Services and loggers remain shared; publication detaches owned settings.
Example:
memorycache.New(func(store *memorycache.Builder) {
store.Cleanup(-time.Second)
})
type BuilderFunc ¶
type BuilderFunc = func(*Builder)
BuilderFunc configures a Builder. Example:
var policy memorycache.BuilderFunc = func(store *memorycache.Builder) {
store.Cleanup(time.Minute)
}
_ = memorycache.New(policy)
type Driver ¶
type Driver struct {
// contains filtered or unexported fields
}
Driver implements cache.Driver in process memory.
Driver is suitable for single-process applications, local development, and tests where persistence across restarts is not required. It is safe for concurrent use. Expiry is checked on access, so correctness never depends on sweeping. Writes sweep expired entries inline at most once per Builder.Cleanup, so memory stays bounded without calling Driver.Start.
Example:
driver := memorycache.New()
if err := driver.Put(ctx, "version", []byte("v1"), time.Minute); err != nil {
return err
}
func New ¶
func New(configure ...BuilderFunc) *Driver
New creates a Driver with the completed construction policies. It starts no goroutines; unless Cleanup is negative, Driver.Start launches a janitor that Driver.Stop ends, and writes sweep expired entries inline either way. Expired entries are never returned, whether or not a sweep ran.
Construction callbacks run directly once, synchronously in order on one fresh draft. Nil entries panic; expanded nil or empty slices omit edits. Publication detaches owned settings, not live dependencies or captures.
Example:
memorycache.New(func(store *memorycache.Builder) {
store.Cleanup(-time.Second)
})
func (*Driver) Add ¶
func (driver *Driver) Add(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error)
Add stores a copy of value only when key is absent or expired.
Example:
added, err := driver.Add(ctx, "receipt", []byte("claimed"), time.Hour)
if err != nil {
return err
}
_ = added
func (*Driver) CompareAndPut ¶
func (driver *Driver) CompareAndPut(ctx context.Context, match cache.Match, entry cache.Entry) (bool, error)
CompareAndPut compares the existing guard and writes entry under one mutex. Missing, expired, or unequal guards return false without changing logical values or lifetimes. A matching guard permits a copied replacement with the requested TTL; a different guard key retains its content and expiry. Cancellation is checked both before waiting and after acquiring the mutex.
Example:
driver := memorycache.New()
if err := driver.Put(ctx, "document", []byte("draft"), time.Minute); err != nil {
return err
}
applied, err := driver.CompareAndPut(ctx,
cache.Match{Key: "document", Value: []byte("draft")},
cache.Entry{Key: "document", Value: []byte("revised"), TTL: time.Minute})
if err != nil {
return err
}
_ = applied
func (*Driver) Decrement ¶
Decrement decreases the integer stored at key by delta and returns the new value. A missing key is created from zero. The remaining TTL is preserved. Subtraction is checked directly, including delta == math.MinInt64. A result outside int64 returns an error wrapping strconv.ErrRange without changing the target value or expiry; a missing target remains absent.
Example:
count, err := driver.Decrement(ctx, "available", 1)
if err != nil {
return err
}
_ = count
func (*Driver) Delete ¶
Delete removes key. Deleting a missing key is a no-op.
Example:
if err := driver.Delete(ctx, "version"); err != nil {
return err
}
func (*Driver) ExtendLock ¶
func (driver *Driver) ExtendLock(ctx context.Context, name, token string, ttl time.Duration) (bool, error)
ExtendLock resets the expiry of name to ttl from now only while it holds token and reports whether it did. It returns an error wrapping cache.ErrInvalidTTL when ttl is not positive.
Example:
extended, err := driver.ExtendLock(ctx, "lock:report", token, time.Minute)
if err != nil {
return err
}
_ = extended
func (*Driver) Get ¶
Get returns a copy of the bytes stored for key. It returns cache.ErrNotFound when the key does not exist or has expired.
Example:
raw, err := driver.Get(ctx, "version")
if err != nil {
return err
}
_ = raw // Independent bytes; mutation does not alter the stored value.
func (*Driver) Has ¶
Has reports whether key exists and has not expired.
Example:
found, err := driver.Has(ctx, "version")
if err != nil {
return err
}
_ = found // Observation only; use an atomic operation to guard a write.
func (*Driver) Increment ¶
Increment increases the integer stored at key by delta and returns the new value. A missing key is created from zero. The remaining TTL is preserved. A mathematical result outside int64 returns an error wrapping strconv.ErrRange without changing the target value or TTL. An absent target remains absent.
Example:
count, err := driver.Increment(ctx, "views", 1)
if err != nil {
return err
}
_ = count
func (*Driver) IncrementWithTTL ¶
func (driver *Driver) IncrementWithTTL(ctx context.Context, key string, delta int64, ttl time.Duration) (int64, time.Duration, error)
IncrementWithTTL increases the integer stored at key by delta, ensures the key expires, and returns the new value with the remaining lifetime. A key that is missing or has no expiry gets ttl; an existing expiry is kept. It returns an error when ttl is not positive. A mathematical result outside int64 returns an error wrapping strconv.ErrRange before changing the target value or expiry. Overflow never adds a TTL to a persistent target or creates an absent one.
Example:
count, remaining, err := driver.IncrementWithTTL(ctx, "requests", 1, time.Minute)
if err != nil {
return err
}
_, _ = count, remaining
func (*Driver) Pull ¶
Pull returns the bytes stored for key and removes the entry under the same lock, so concurrent callers cannot both receive the value. It returns cache.ErrNotFound when the key does not exist or has expired.
Example:
raw, err := driver.Pull(ctx, "one-time-token")
if err != nil {
return err
}
_ = raw // The entry was removed atomically with this read.
func (*Driver) Put ¶
Put stores a copy of value for key. A zero ttl stores the entry without expiration.
Example:
if err := driver.Put(ctx, "version", []byte("v1"), time.Minute); err != nil {
return err
}
func (*Driver) Start ¶
Start launches the janitor unless Cleanup is negative. Starting an already started driver does nothing.
Example:
driver := memorycache.New()
if err := driver.Start(ctx); err != nil {
return err
}
return driver.Stop(ctx)
func (*Driver) Stop ¶
Stop ends the janitor and waits for it to exit or ctx to end. The driver stays usable afterwards; expired entries are then removed by access and by inline sweeps on writes.
Example:
cleanup, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := driver.Stop(cleanup); err != nil {
return err
}
func (*Driver) TTL ¶
TTL returns the remaining lifetime for key, or zero when it never expires. It returns cache.ErrNotFound when the key does not exist or has expired.
Example:
remaining, err := driver.TTL(ctx, "version")
if err != nil {
return err
}
_ = remaining
func (*Driver) TryLock ¶
func (driver *Driver) TryLock(ctx context.Context, name, token string, ttl time.Duration) (bool, error)
TryLock stores token under name for ttl when name is absent or expired, and reports whether it did. The entry is an ordinary one, so an expired lock is replaced like any expired key. It returns an error wrapping cache.ErrInvalidTTL when ttl is not positive.
Example:
token := rand.Text() // crypto/rand: unique to this attempt.
held, err := driver.TryLock(ctx, "lock:report", token, time.Minute)
if err != nil {
return err
}
if held {
_, err = driver.Unlock(ctx, "lock:report", token)
}
return err