feat(keyvalue): add RememberFor for TTL-cached values

This commit is contained in:
kolaente 2026-05-30 14:57:15 +02:00 committed by kolaente
parent 1af6d7763b
commit ec2f154e10
1 changed files with 37 additions and 0 deletions

View File

@ -17,6 +17,8 @@
package keyvalue
import (
"time"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/modules/keyvalue/memory"
@ -142,3 +144,38 @@ func RememberValue[T any](key string, fn func() (T, error)) (T, error) {
return val, nil
}
// expiringValue wraps a cached value with the time it expires.
type expiringValue[T any] struct {
Value T
ExpiresAt time.Time
}
// RememberFor is like RememberValue but treats the cached value as stale once it is
// older than ttl. On a miss or once expired, it executes fn, caches the result for
// ttl and returns it. If fn returns an error, nothing is cached.
// T must be a concrete (non-pointer) type.
func RememberFor[T any](key string, ttl time.Duration, fn func() (T, error)) (T, error) {
var cached expiringValue[T]
exists, err := GetWithValue(key, &cached)
if err != nil {
var zero T
return zero, err
}
if exists && time.Now().Before(cached.ExpiresAt) {
return cached.Value, nil
}
val, err := fn()
if err != nil {
var zero T
return zero, err
}
if err := Put(key, expiringValue[T]{Value: val, ExpiresAt: time.Now().Add(ttl)}); err != nil {
var zero T
return zero, err
}
return val, nil
}