mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[feature] Read + Write tombstones for deleted Actors (#1005)
* [feature] Read + Write tombstones for deleted Actors * copyTombstone * update to use resultcache instead of old ttl cache Signed-off-by: kim <grufwub@gmail.com> * update go-cache library to fix result cache capacity / ordering bugs Signed-off-by: kim <grufwub@gmail.com> * bump go-cache/v3 to v3.1.6 to fix bugs Signed-off-by: kim <grufwub@gmail.com> * switch on status code * better explain ErrGone reasoning Signed-off-by: kim <grufwub@gmail.com> Co-authored-by: kim <grufwub@gmail.com>
This commit is contained in:
184
vendor/codeberg.org/gruf/go-cache/v3/result/key.go
generated
vendored
Normal file
184
vendor/codeberg.org/gruf/go-cache/v3/result/key.go
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
package result
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"codeberg.org/gruf/go-byteutil"
|
||||
"codeberg.org/gruf/go-mangler"
|
||||
)
|
||||
|
||||
// structKeys provides convience methods for a list
|
||||
// of struct field combinations used for cache keys.
|
||||
type structKeys []keyFields
|
||||
|
||||
// get fetches the key-fields for given lookup (else, panics).
|
||||
func (sk structKeys) get(lookup string) *keyFields {
|
||||
for i := range sk {
|
||||
if sk[i].lookup == lookup {
|
||||
return &sk[i]
|
||||
}
|
||||
}
|
||||
panic("unknown lookup: \"" + lookup + "\"")
|
||||
}
|
||||
|
||||
// generate will calculate the value string for each required
|
||||
// cache key as laid-out by the receiving structKeys{}.
|
||||
func (sk structKeys) generate(a any) []cacheKey {
|
||||
// Get reflected value in order
|
||||
// to access the struct fields
|
||||
v := reflect.ValueOf(a)
|
||||
|
||||
// Iteratively deref pointer value
|
||||
for v.Kind() == reflect.Pointer {
|
||||
if v.IsNil() {
|
||||
panic("nil ptr")
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
// Preallocate expected slice of keys
|
||||
keys := make([]cacheKey, len(sk))
|
||||
|
||||
// Acquire byte buffer
|
||||
buf := bufpool.Get().(*byteutil.Buffer)
|
||||
defer bufpool.Put(buf)
|
||||
|
||||
for i := range sk {
|
||||
// Reset buffer
|
||||
buf.B = buf.B[:0]
|
||||
|
||||
// Set the key-fields reference
|
||||
keys[i].fields = &sk[i]
|
||||
|
||||
// Calculate cache-key value
|
||||
keys[i].populate(buf, v)
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
// cacheKey represents an actual cache key.
|
||||
type cacheKey struct {
|
||||
// value is the actual string representing
|
||||
// this cache key for hashmap lookups.
|
||||
value string
|
||||
|
||||
// fieldsRO is a read-only slice (i.e. we should
|
||||
// NOT be modifying them, only using for reference)
|
||||
// of struct fields encapsulated by this cache key.
|
||||
fields *keyFields
|
||||
}
|
||||
|
||||
// populate will calculate the cache key's value string for given
|
||||
// value's reflected information. Passed encoder is for string building.
|
||||
func (k *cacheKey) populate(buf *byteutil.Buffer, v reflect.Value) {
|
||||
// Append each field value to buffer.
|
||||
for _, idx := range k.fields.fields {
|
||||
fv := v.Field(idx)
|
||||
fi := fv.Interface()
|
||||
buf.B = mangler.Append(buf.B, fi)
|
||||
buf.B = append(buf.B, '.')
|
||||
}
|
||||
|
||||
// Drop last '.'
|
||||
buf.Truncate(1)
|
||||
|
||||
// Create string copy from buf
|
||||
k.value = string(buf.B)
|
||||
}
|
||||
|
||||
// keyFields represents a list of struct fields
|
||||
// encompassed in a single cache key, the string name
|
||||
// of the lookup, and the lookup map to primary keys.
|
||||
type keyFields struct {
|
||||
// lookup is the calculated (well, provided)
|
||||
// cache key lookup, consisting of dot sep'd
|
||||
// struct field names.
|
||||
lookup string
|
||||
|
||||
// fields is a slice of runtime struct field
|
||||
// indices, of the fields encompassed by this key.
|
||||
fields []int
|
||||
|
||||
// pkeys is a lookup of stored struct key values
|
||||
// to the primary cache lookup key (int64).
|
||||
pkeys map[string]int64
|
||||
}
|
||||
|
||||
// populate will populate this keyFields{} object's .fields member by determining
|
||||
// the field names from the given lookup, and querying given reflected type to get
|
||||
// the runtime field indices for each of the fields. this speeds-up future value lookups.
|
||||
func (kf *keyFields) populate(t reflect.Type) {
|
||||
// Split dot-separated lookup to get
|
||||
// the individual struct field names
|
||||
names := strings.Split(kf.lookup, ".")
|
||||
if len(names) == 0 {
|
||||
panic("no key fields specified")
|
||||
}
|
||||
|
||||
// Pre-allocate slice of expected length
|
||||
kf.fields = make([]int, len(names))
|
||||
|
||||
for i, name := range names {
|
||||
// Get field info for given name
|
||||
ft, ok := t.FieldByName(name)
|
||||
if !ok {
|
||||
panic("no field found for name: \"" + name + "\"")
|
||||
}
|
||||
|
||||
// Check field is usable
|
||||
if !isExported(name) {
|
||||
panic("field must be exported")
|
||||
}
|
||||
|
||||
// Set the runtime field index
|
||||
kf.fields[i] = ft.Index[0]
|
||||
}
|
||||
}
|
||||
|
||||
// genkey generates a cache key for given key values.
|
||||
func genkey(parts ...any) string {
|
||||
if len(parts) < 1 {
|
||||
// Panic to prevent annoying usecase
|
||||
// where user forgets to pass lookup
|
||||
// and instead only passes a key part,
|
||||
// e.g. cache.Get("key")
|
||||
// which then always returns false.
|
||||
panic("no key parts provided")
|
||||
}
|
||||
|
||||
// Acquire buffer and reset
|
||||
buf := bufpool.Get().(*byteutil.Buffer)
|
||||
defer bufpool.Put(buf)
|
||||
buf.Reset()
|
||||
|
||||
// Encode each key part
|
||||
for _, part := range parts {
|
||||
buf.B = mangler.Append(buf.B, part)
|
||||
buf.B = append(buf.B, '.')
|
||||
}
|
||||
|
||||
// Drop last '.'
|
||||
buf.Truncate(1)
|
||||
|
||||
// Return string copy
|
||||
return string(buf.B)
|
||||
}
|
||||
|
||||
// isExported checks whether function name is exported.
|
||||
func isExported(fnName string) bool {
|
||||
r, _ := utf8.DecodeRuneInString(fnName)
|
||||
return unicode.IsUpper(r)
|
||||
}
|
||||
|
||||
// bufpool provides a memory pool of byte
|
||||
// buffers use when encoding key types.
|
||||
var bufpool = sync.Pool{
|
||||
New: func() any {
|
||||
return &byteutil.Buffer{B: make([]byte, 0, 512)}
|
||||
},
|
||||
}
|
Reference in New Issue
Block a user